Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP mktime and timezone

I'm working on some time related features and I opt to always use UTC times and store time stamps as integers for consistency.

However, I noticed that when I use mktime it seems that the currently set time zone has an influence of the return value of mktime. From the documentation I understand that mktime is supposed to return the number of seconds since epoch:

Returns the Unix timestamp corresponding to the arguments given. This timestamp is a long integer containing the number of seconds between the Unix Epoch (January 1 1970 00:00:00 GMT) and the time specified.

http://php.net/manual/en/function.mktime.php

However, it seems that mktime is including the time zone that is currently set. When using the following code:

date_default_timezone_set('UTC');
$time = mktime(0, 0, 0, 1, 1, 2016 );
echo "{$time}\n";

date_default_timezone_set('Australia/Sydney');
$time = mktime(0, 0, 0, 1, 1, 2016 );
echo "{$time}\n";

I would expect the two time vales to be same but apparently they are not:

1451606400
1451566800

Which seems to be exacly an 11 hour difference:

1451606400 - 1451566800 = 39600 / (60*60) = 11

What do I not understand correctly about mktime and/or why is the time zone taken into account when using mktime?

like image 962
Luke Avatar asked Jan 07 '23 10:01

Luke


2 Answers

I can't tell you why it is the way it is (PHP has never made sense to me when it comes to date and time) but there is an alternative function gmmktime() which is

Identical to mktime() except the passed parameters represents a GMT date. gmmktime() internally uses mktime() so only times valid in derived local time can be used.

There is also a comment on the PHP documentation for this function which explains how mktime(), gmmktime() and time() work. Essentially, they assume that you always think in time zones even if a UNIX timestamp itself doesn't carry a timezone.

like image 110
jsfan Avatar answered Jan 09 '23 00:01

jsfan


Resulting Unix timestamp are indeed encoded in a timezone agnostic way, but input arguments are interpreted relative to the timezone set for current process. And indeed, Sidneys 2016-01-01 00:00:00 (GMT+11) happened 11 hours before UTC 2016-01-01 00:00:00. When some foreigner tells you a time, you have to know its time zone to correctly interpret it, and so does mktime().

If dates you want to pass to mktime() are UTC dates, then use gmmktime() which exists for that purpose.

like image 41
TrogloGeek Avatar answered Jan 09 '23 00:01

TrogloGeek