Matty
Matty

Reputation: 34413

PHP: Why is this code erroneously returning zero?

I'm calculating the offset between two timezones, but I'm seeing a result I don't expect (zero) with the following code:

$datetimezone_london = new DateTimeZone('Europe/London');  
$datetimezone_client = new DateTimeZone('Australia/Canberra');  
$now_client = new DateTime("now", $datetimezone_client);  
$offset = $datetimezone_london->getOffset($now_client);  
echo $offset;

If I flip the timezone strings, it works, but surely the above code should work too. What's happening?

Upvotes: 0

Views: 176

Answers (2)

Alnitak
Alnitak

Reputation: 339786

getOffset() returns the offset to GMT in seconds, and London is currently on GMT, hence the return value is zero.

I believe what you need instead is:

$tz_london = new DateTimeZone('Europe/London');  
$tz_client = new DateTimeZone('Australia/Canberra');
$time_london = new DateTime('now', $tz_london);  
$time_client = new DateTime('now', $tz_client);
$offset = $time_client->getOffset() - $time_london->getOffset();  
echo $offset;

This currently (in January) returns 39600 (11 hours). In July it returns 9 hours, and in mid October (where there's a short period when both Europe and Australia are in daylight saving) it returns 10 hours.

Upvotes: 2

Andrew Moore
Andrew Moore

Reputation: 95314

DateTimeZone::getOffset() works a bit differently that what most people think. It calculates the offset to GMT of the instance DateTimeZone offset for the date passed as parameter. The date passed as parameter is then converted to the same timezone as the instance (DST and other rules applying) and the offset is calculated for that date.

So your code right now calculates the offset to GMT of the timezone Europe/London.. Since Europe/London is on GMT right now (versus BMT), you are getting 0. (Try a date in August, you'll get 36000).

If you want the current difference between two timezones, use this code...

function timezone_diff($origin, $compareTo, $forDate = "now") {
    $dtzOrigin = new DateTimeZone($origin);
    $dtzCompareTo = new DateTimeZone($compareTo);

    $compareDate = new DateTime($forDate);

    $offsetOrigin = $dtzOrigin->getOffset($compareDate);
    $offsetCompareTo = $dtzCompareTo->getOffset($compareDate);

    return $offsetCompareTo - $offsetOrigin;
}

Upvotes: 1

Related Questions