Несоответствие даты и времени PHP? Что мне не хватает?

Используя PHP 5.2.5, я работал с некоторыми объектами DateTime и заметил, что время кажется неправильным. Проблема, с которой я сталкиваюсь, может быть связана с часовыми поясами, но я не уверен - я создаю DateTime из метки времени Unix и получаю разные/неожиданные результаты в зависимости от того, как я его вывожу.

Я создал следующее, чтобы легко проиллюстрировать «проблему»:

$timezone = new DateTimeZone('America/Chicago'); 
$now = time(); 
$now_datetime = new DateTime('@' . $now, $timezone); 
echo phpversion() . "\n\n"; 
echo $now . "\n"; 
echo $now_datetime->format('U') . "\n\n"; 
echo date('g:i:sa', $now) . "\n";
echo $now_datetime->format('g:i:sa') . "\n\n";

Это выводит следующее:

5.2.5

1287676530
1287676530

10:55:30am
3:55:30pm

В настоящее время я нахожусь в правильном часовом поясе, и сервер показывает «правильное» время (10:00) при использовании функции date() для вывода форматированной даты, а также «Америка/Чикаго» является часовым поясом по умолчанию на этой машине. Но при выводе значений через DateTime::format() времена совсем другие.

Я добавил ->format('U') только для того, чтобы убедиться, что он содержит правильную метку времени.

Итак, я, вероятно, делаю что-то не так или у меня неправильные ожидания. Итак, что я упускаю?

Похоже, проблема с часовым поясом в DateTime, но если это так, то почему «сейчас» в Америке/Чикаго отображается как ... неправильно?


person anonymous coward    schedule 21.10.2010    source источник


Ответы (2)


Часовой пояс, который вы «вставляете» в DateTime, является часовым поясом строки, который может не совпадать с вашим текущим часовым поясом, поэтому PHP может вычислить фактическую дату и время, а не часовой пояс, который он использует для format вашего вывода. Если вы хотите, чтобы он выводил время в определенном часовом поясе, используйте $now_datetime->setTimezone($timezone).

person Wrikken    schedule 21.10.2010
comment
Этот ответ фактически привел меня к решению после того, как @Pekka предоставил разъяснения. Поскольку PHP отбрасывает информацию о часовом поясе при предоставлении метки времени конструктору, он (очевидно?) не запоминает этот часовой пояс для последующего вывода. Таким образом, как вы сказали, я должен явно использовать setTimezone(), прежде чем пытаться получить вывод. Мне это кажется немного странным, но работает корректно. - person anonymous coward; 21.10.2010
comment
Если вам это нужно во всем приложении (а не только для каждого объекта TimeDate), вызовите date_default_timezone_set('America/Chicago'); - person Wrikken; 21.10.2010

В руководстве по конструктору DateTime есть ответ:

Параметр $timezone и текущий часовой пояс игнорируются, если параметр $time является отметкой времени UNIX (например, @946684800) или указывает часовой пояс (например, 2010-01-28T15:00:00+02:00).

Это означает, что ваша временная метка рассматривается как GMT, что объясняет разницу в 7 часов.

person Pekka    schedule 21.10.2010
comment
Я насчитал 5 часов, но в любом случае: если часовой пояс отброшен (что я пропустил), как я могу указать DateTime, чтобы выводить это время в мое текущее время? EDIT: обдумав ответ @Wrikken, я понял, как это исправить. Спасибо! - person anonymous coward; 21.10.2010
comment
@anon, ты прав, это 5, конечно. Хм... Вместо этого я бы снабдил его выходом date(): date("d.m.Y H:i:s"); и добавил смещение часового пояса вручную: +0500 (или -0500, что бы ни применимо), таким образом, внутреннее время в Datetime было правильным - person Pekka; 21.10.2010
comment
@Wrikken указал, что часовой пояс должен быть установлен явно. Это своего рода имеет смысл, поскольку вы указали, что PHP отбрасывает любую входящую информацию о часовом поясе при предоставлении метки времени конструктору DateTime. Моя проблема заключалась в том, что я предполагал, что предоставленная информация о часовом поясе останется для последующего расчета (вывод через format()) и т. д. Спасибо! - person anonymous coward; 21.10.2010