Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adjusting time zone in PHP with DateTime / DateTimeZone

There's a lot of info on doing time zone adjustments in PHP, but I haven't found an answer for specifically what I want to do due to all the noise.

Given a time in one timezone, I want to convert it to the time in another timezone.

This is essentially what I want to do, but I need to be able to do it using only the built-in PHP libs, not PEAR Date.

This is what I've been doing, but it seems to always give me the offset relative to GMT:

$los_angeles_time_zone = new DateTimeZone('America/Los_Angeles');
$hawaii_time_zone = new DateTimeZone('Pacific/Honolulu');

$date_time_los_angeles = new DateTime('2009-09-18 05:00:00', $los_angeles_time_zone);
printf("LA Time: %s<br/>", $date_time_los_angeles->format(DATE_ATOM));

$time_offset = $hawaii_time_zone->getOffset($date_time_los_angeles);
printf("Offset: %s<br/>", $time_offset);

This is the output:

LA Time: 2009-09-18T05:00:00-07:00
Offset: -36000

I was expecting 3 hours (10800 seconds). but the '-7:00' thing tells me it's keeping everything relative to GMT, which maybe explains why it's giving me the "absolute" offset.

How do I just get the offset between the two timezones without all of this GMT hoohah?

Thanks.

UPDATE:

I occured to me that I could do this and get what I want:

    $date_time_los_angeles = new DateTime('2009-09-18 05:00:00', $los_angeles_time_zone);
printf("LA Time: %s<br/>", $date_time_los_angeles->format(DATE_ATOM));

$date_time_hawaii = new DateTime('2009-09-18 05:00:00', $hawaii_time_zone);
printf("Hawaii Time: %s<br/>", $date_time_hawaii->format(DATE_ATOM));


$time_offset = $los_angeles_time_zone->getOffset($date_time_los_angeles) - $hawaii_time_zone->getOffset($date_time_los_angeles);
printf("Offset: %s<br/>", $time_offset);

But it feels awkward to me. Anyone know a cleaner way to do it?

like image 563
pjbeardsley Avatar asked Sep 18 '09 14:09

pjbeardsley


2 Answers

Here are a couple of functions using the DateTime classes. The first one will return the difference in seconds between two timezones. The second returns a "translation" of the time from one timezone to another.

function timezone_diff($tz_from, $tz_to, $time_str = 'now')
{
    $dt = new DateTime($time_str, new DateTimeZone($tz_from));
    $offset_from = $dt->getOffset();
    $timestamp = $dt->getTimestamp();
    $offset_to = $dt->setTimezone(new DateTimezone($tz_to))->setTimestamp($timestamp)->getOffset();
    return $offset_to - $offset_from;
}

function time_translate($tz_from, $tz_to, $time_str = 'now', $format = 'Y-m-d H:i:s')
{
    $dt = new DateTime($time_str, new DateTimezone($tz_from));
    $timestamp = $dt->getTimestamp();
    return $dt->setTimezone(new DateTimezone($tz_to))->setTimestamp($timestamp)->format($format);
}

Demo:

$los_angeles_time = '2009-09-18 05:00:00';
$los_angeles_tz   = 'America/Los_Angeles';
$hawaii_tz        = 'Pacific/Honolulu';

$los_angeles_hawaii_diff = timezone_diff($los_angeles_tz, $hawaii_tz, $los_angeles_time);
echo $los_angeles_hawaii_diff . '<br />';

$hawaii_time = time_translate($los_angeles_tz, $hawaii_tz, $los_angeles_time);
echo $hawaii_time . '<br />';
like image 143
GZipp Avatar answered Sep 29 '22 15:09

GZipp


As GZipp commented, his code is really only for PHP >= 5.3.0. That is fine, but - here's a version that will work in PHP >= 5.2.0. (Incidentally, it also works in 5.3+, and with 2 less function calls)

<?php
function time_translate($tz_from, $tz_to, $time_str = 'now', $format = 'Y-m-d H:i:s')
{
    $dt = new DateTime($time_str, new DateTimezone($tz_from));
    $dt->setTimezone(new DateTimezone($tz_to));
    return $dt->format($format);
}

$time_diffs = array('now', '-1 hour', '-1 day', '-1 week', '-1 month', '+1 hour', '+1 week', '+1 month');

foreach ($time_diffs as $diff)
{
 echo "{$diff}:"
  . "\n\t"
  . "Current: " . date("Y-m-d H:i:s", strtotime($diff))
  . "\n\t"
  . "UTC: " . time_translate("US/Eastern", "UTC", $diff)
  . "\n\n";
}
like image 39
Jim Rubenstein Avatar answered Sep 29 '22 15:09

Jim Rubenstein