Как включить полную поддержку UTC для високосных секунд в PHP DateTime?
Я хотел сделать немного DateTime
расчеты с Leap Seconds, но он остановился довольно рано, потому что я не мог сказать DateTime
что я имел ввиду:
### June 30, 2012 at 23:59:60 UTC ###
$leap = new DateTime('2012-06-30T23:59:60UTC');
var_export($leap);
Выход:
DateTime::__set_state(array(
'date' => '2012-07-01 00:00:00',
'timezone_type' => 3,
'timezone' => 'UTC',
))
Я не могу создать DateTime
для этого UTC високосная секунда прошлого года (также не другие високосные секунды, которые я попробовал). Интересно, если DateTime
поддерживает високосные секунды вообще, я думал, что есть поддержка UTC, но, вероятно, не для високосных секунд, так что просто поддержка GMT?
2 ответа
Время UNIX не знает о високосных секундах. Что касается этого, каждый день состоит ровно из 86 400 секунд, а время просто пропускает или повторяет секунду время от времени. (Это в значительной степени необходимо, потому что високосные секунды не полностью запланированы заранее. Если бы високосные секунды были подсчитаны во времени UNIX, "отображение" между временем UNIX и удобочитаемыми датами / временем изменится непредсказуемо, так как были объявлены високосные секунды.)
Поскольку все примитивы даты / времени основаны на времени UNIX, PHP также не может легко представлять високосные секунды. Они эффективно невидимы.
Это не совсем ответ, но, по крайней мере, это что-то.
Здесь есть две возможные проблемы:
- Как упомянул ircmaxell, PHP может потреблять дополнительную секунду где-то внутри битов манипуляции с часовым поясом, но необходимы дополнительные исследования.
- Однако я лично ожидаю, что PHP "исправит" "переполнение" секунд в минуты.
DateTime
конструктор передает заданный аргумент через тот же код, который обрабатываетstrtotime
Хорошо известно, что они принимают полностью фиктивные даты (например, 31 февраля) и превращают их во что-то, что, возможно, имеет смысл.
Единственная ссылка на високосные секунды в документации strptime
:
"tm_sec" включает в себя любые високосные секунды (в настоящее время до 2 в год).
Например, сокращенно от интерактивного приглашения PHP:
php > $eviler_format = '%Y-%m-%d %H:%M:%S %z';
php > $evil = '2012-12-31 23:59:59 +0000';
php > var_dump(strptime($evil, $eviler_format));
array(9) {
'tm_sec' =>
int(59) // ...
}
php > $evil = '2012-12-31 23:59:60 +0000';
php > var_dump(strptime($evil, $eviler_format));
array(9) {
'tm_sec' =>
int(60) // ...
}
php > $evil = '2012-12-31 23:59:61 +0000';
php > var_dump(strptime($evil, $eviler_format));
array(9) {
'tm_sec' =>
int(61) // ...
}
php > $evil = '2012-12-31 23:59:62 +0000';
php > var_dump(strptime($evil, $eviler_format));
bool(false)
К сожалению, также требуются "високосные секунды", которых нет 31 декабря:
php > $evil = '2012-01-07 23:59:61 +0000';
php > var_dump(strptime($evil, $eviler_format));
array(9) {
'tm_sec' =>
int(61)
'tm_min' =>
int(59)
'tm_hour' =>
int(23)
'tm_mday' =>
int(7)
'tm_mon' =>
int(0)
'tm_year' =>
int(112)
'tm_wday' =>
int(6)
'tm_yday' =>
int(6)
'unparsed' =>
string(0) ""
}
или не в полночь:
php > $evil = '2012-01-07 08:59:61 +0000';
php > var_dump(strptime($evil, $eviler_format));
array(9) {
'tm_sec' =>
int(61)
'tm_min' =>
int(59)
'tm_hour' =>
int(8)
'tm_mday' =>
int(7)
'tm_mon' =>
int(0)
'tm_year' =>
int(112)
'tm_wday' =>
int(6)
'tm_yday' =>
int(6)
'unparsed' =>
string(0) ""
}
Кроме того, это полностью презентационная функция, которая не привязана к DateTime
в любом случае. Вы не можете делать математику на этом, и получить реальные високосные секунды невозможно в реальной жизни, учитывая четко определенную природу вещей. Здесь бесполезно.
Вывод: PHP не думает о високосных секундах. Убедитесь, что ваш сервер синхронизирован с вышестоящим NTP-сервером, который заботится об этом, и в конечном итоге все будет в порядке. Если вам нужно позаботиться о точности второго уровня в отношении високосных секунд, возможно, PHP в любом случае вам не подходит.