Viewed   64 times

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?

 Answers

2

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 />';
Sunday, October 9, 2022
 
2

If you you install the PHP Internationalization Package, you can do the following:

IntlTimeZone::createTimeZone('America/New_York')->getDisplayName()

This will return the CLDR English standard-long form by default, which is "Eastern Standard Time" in this case. You can find the other options available here. For example:

IntlTimeZone::createTimeZone('Europe/Paris')->getDisplayName(true, IntlTimeZone::DISPLAY_LONG, 'fr_FR')

The above will return "heure avancée d’Europe centrale" which is French for Central European Summer Time.

Be careful to pass the first parameter as true if DST is in effect for the date and time in question, or false otherwise. This is illustrated by the following technique:

$tz = 'America/New_York';
$dt = new DateTime('2016-01-01 00:00:00', new DateTimeZone($tz));
$dst = $dt->format('I');
$text = IntlTimeZone::createTimeZone($tz)->getDisplayName($dst);
echo($text); // "Eastern Standard Time"

Working PHP Fiddle Here

Please note that these strings are intended for display to an end user. If your intent is to use them for some programmatically purpose, such as calling into another API, then they are not appropriate - even if the English versions of some of the strings happen to align. For example, if you are sending the time zone to a Windows or .NET API, or to a Ruby on Rails API, these strings will not work.

Friday, December 23, 2022
 
slhck
 
1

Function date_default_timezone_set()>= 5.1.0 set timezone globally.

If you need to set timezone locally, for specific variable, you can use DateTime>= 5.2.0 and DateTimezone>= 5.2.0 classes, like:

$dt = new DateTime('now', new DateTimezone('Asia/Dhaka'));
echo $dt->format('F j, Y, g:i a');

Here is the list of all available timezones in PHP.


Since non of the above functions will work on PHP version 4.x, you have no other way to set timezone, rather that setting your server time to your timezone, or add offset to time() functions, like:

echo date('F j, Y, g:i a', time() - 6*3600); # Bangladesh is in UTC+6
Saturday, September 10, 2022
2

The reason for this behaviour is that when you don't specify the missing parts of a date/time input to DateTime::createFromFormat, it uses the values from the current local date and time. In Auckland, that is October 31st and so it tries to make a date out of September 31 2019, which comes out as October 1 2019. To avoid this problem, use a ! at the start of the format string; this will instead substitute values from January 1 1970, 00:00:00 (the Unix Epoch) as required for those that are not specified in the time value:

echo DateTime::createFromFormat('!F-Y', 'September-2019')
    ->setTimeZone(new DateTimeZone('Pacific/Auckland'))
    ->format('Y-m-d');

Output:

2019-09-01

Demo on 3v4l.org

Monday, November 7, 2022
43

Based on @Ramhound's comments and my own research, the answer is that Excel knows nothing about time zones and so this is not possible, although I have not found a definitive statement to that effect.

This documentation page from Microsoft describes how Excel represents dates and makes no mention of time zones, implying that Excel does not support them:

https://support.office.com/en-us/article/Change-the-date-system-format-or-two-digit-year-interpretation-aaa2159b-4ae8-4651-8bce-d4707bc9fb9f

Microsoft Office Excel stores dates as sequential numbers that are called serial values.

The existence of many partial solutions from outside Microsoft supports the suggestion that this is not possible, e.g.:

https://exceljet.net/formula/convert-time-to-time-zone

The answer to this question might help if VB scripting is possible, as it brings some Windows system time zone conversion functions into Excel:

https://.com/questions/4896116/parsing-an-iso8601-date-time-including-timezone-in-excel

It seems that Power Query supports time zones and conversions, which may be an option for Excel users requiring this:

https://msdn.microsoft.com/en-us/library/mt296609.aspx

Sunday, August 28, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :