Многие разработчики на 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. Я пытался устанавливать временную зону и для остальных объектов даты, но изменений это не принесло, поэтому я этого и не описывал.
Все бы хорошо, да есть у данного класса проблемка, с которой я столкнулся только недавно.
Объект класса 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. Я пытался устанавливать временную зону и для остальных объектов даты, но изменений это не принесло, поэтому я этого и не описывал.