Pull to refresh

PHP: проблема с timestamp в DateTime

Reading time3 min
Views3.1K
Многие разработчики на PHP используют объекты класса DateTime. Об удобствах его я писать не буду, тем более на Хабре уже была статья об этом классе, не об этом речь.
Все бы хорошо, да есть у данного класса проблемка, с которой я столкнулся только недавно.

Объект класса DateTime в PHP можно создать как стандартным методом:

$date = new DateTime(«2009-01-21»);

так и функцией date_create, входящей в состав PHP начиная с версии 5.2.0:

$date date_create(«2009-01-21»);

Конструктор принимает как параметр строку, которая определяет дату и время, также это могут быть названия дней недели и куча других параметров, которые описаны в документации к функции strtotime. Еще есть возможность передавать в конструктор метку времени (timestamp), поместив ее после символа "@", к примеру, так:

$date = new DateTime("@1232488800");

Именно с этим параметром и возникли некоторые непонятки.
Для вывода информации о конкретном объекте даты создадим следующую функцию:

function date_info(DateTime $date){
    echo 
"<br>";
    echo 
«Timestamp: ».$date->format(«U»).' - '.$date->format(«d/m/Y H:i:s»)."<br>";
    
$tz $date->getTimezone();
    echo 
«Timezone: ».$tz->getName()." (Offset: ".$date->getOffset()." sec.)<br>";
}

В ней мы выводим на экран следующие сведения:
— метку времени
— саму дату и время
— временную зону
— смещение в секундах этой самой временной зоны

Создаем объекты даты и выводим информацию о нем

$date1 = new DateTime(«2009-01-21 00:00:00»);
date_info($date1);

получили

Timestamp: 1232488800 — 21/01/2009 00:00:00
Timezone: Europe/Helsinki (Offset: 7200 sec.)

хорошо, у нас есть метка, дата и временная зона.
Создадим другой объект, передадим ему в параметр название недели того же дня — «Wednesday».

$date2 = new DateTime(«Wednesday»);
date_info($date2);

Так как это ближайшая среда, то дата будет той же

Timestamp: 1232488800 — 21/01/2009 00:00:00
Timezone: Europe/Helsinki (Offset: 7200 sec.)

Замечательно. Теперь у нас есть 2 одинаковые метки времени и совпадающие даты.

Теперь внимание, создаем объект с параметром временной метки и выводим информацию о нем

$date3 = new DateTime("@1232488800");
date_info($date3);

и что же мы видим:

Timestamp: 1232488800 — 20/01/2009 22:00:00
Timezone: Europe/Helsinki (Offset: 7200 sec.)

Метка времени осталась той же, временная зона тоже не поменялась, а вот дата и время сместились на время, соответствующие смещению временной зоны, только со знаком минус. То есть смещение как таковое у нас не сработало.

Я с недоумением смотрел на результат и не мог понять, как это возможно. Заново пересмотрел документацию — вроде все правильно сделал.

Решилось все, как обычно, методом научного тыка. Я подумал, а почему бы мне не применить к объекту его текущую временную зону

$date->setTimezone(new DateTimeZone(«Europe/Helsinki»));
date_info($date);

и, О ЧУДО! Скрипт выдал мне нужную дату.

Timestamp: 1232488800 — 21/01/2009 00:00:00
Timezone: Europe/Helsinki (Offset: 7200 sec.)

Делал все эти телодвижения я в Виндовсе, стал уже грешить на нее, но попробовав в Линкусе, и получив тот же результат, кошусь в сторону разработчиков языка. Версия PHP в обеих ОСях 5.2.4, так что, возможно, в более новых версиях уже исправлено. Но кто предупрежден — тот вооружен.

P.S. Я пытался устанавливать временную зону и для остальных объектов даты, но изменений это не принесло, поэтому я этого и не описывал.
Tags:
Hubs:
+3
Comments8

Articles

Change theme settings