PHP mktime и часовой пояс

Я работаю над некоторыми функциями, связанными со временем, и я предпочитаю всегда использовать время UTC и хранить метки времени как целые числа для согласованности.

Однако я заметил, что когда я использую mktime, кажется, что установленный в данный момент часовой пояс влияет на возвращаемое значение mktime. Из документации я понимаю, что mktime должен возвращать количество секунд с начала эпохи:

Возвращает временную метку Unix, соответствующую заданным аргументам. Эта отметка времени представляет собой длинное целое число, содержащее количество секунд между эпохой Unix (1 января 1970 г., 00:00:00 по Гринвичу) и указанным временем.

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

Однако кажется, что mktime включает часовой пояс, который установлен в настоящее время. При использовании следующего кода:

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";

Я ожидал бы, что два значения времени будут одинаковыми, но, по-видимому, это не так:

1451606400
1451566800

Кажется, разница составляет ровно 11 часов:

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

Что я не правильно понимаю в mktime и/или почему при использовании mktime учитывается часовой пояс?


person Luke    schedule 18.03.2016    source источник


Ответы (2)


Я не могу сказать вам, почему это так (PHP никогда не имел для меня смысла, когда дело доходит до даты и времени), но есть альтернативная функция gmmktime(), который

Идентичен mktime(), за исключением того, что переданные параметры представляют дату по Гринвичу. gmmktime() внутренне использует mktime(), поэтому можно использовать только время, действительное в производном местном времени.

Существует также комментарий к документации PHP для этой функции, объясняющий, как mktime(), gmmktime() и time() работают. По сути, они предполагают, что вы всегда думаете о часовых поясах, даже если временная метка UNIX не содержит часовой пояс.

person jsfan    schedule 18.03.2016
comment
Ой. Это довольно ужасно. Все, что им нужно было сделать, это всегда использовать UTC во всех функциях времени и включать часовой пояс только при отображении времени. Я предполагаю, что это из-за истории PHP... Спасибо за ваш ответ! - person Luke; 19.03.2016

Результирующая временная метка Unix действительно закодирована независимо от часового пояса, но входные аргументы интерпретируются относительно часового пояса, установленного для текущего процесса. И действительно, Сидней 2016-01-01 00:00:00 (GMT+11) случился за 11 часов до UTC 2016-01-01 00:00:00. Когда какой-то иностранец сообщает вам время, вы должны знать его часовой пояс, чтобы правильно интерпретировать его, и то же самое делает mktime().

Если даты, которые вы хотите передать в mktime(), являются датами UTC, используйте gmmktime( ), который существует для этой цели.

person TrogloGeek    schedule 15.07.2020