Однажды мне пришлось столкнуться с исправлением бага на сайте. Все казалось просто. Я работал с JDate
и пришлось иметь дело с часовыми поясами. Мне показалось, что хватит двух часов для того, чтобы все завершить. В итоге я потратил на это полтора дня.
Разберемся с проблемой более детально. Пользовать А заполняет форму с полем, в котором содержится дата. Лучший способ хранить дату в БД – это конвертировать ее в UTC (Всемирное координированное время). Что такое UTC? Всегда можно использовать начальную точку, а в последствии добавлять часовые пояса в зависимости от местонахождения пользователя. Важно знать, как конвертировать дату обратно в UTC. С этим может помочь JDate
. Если взглянуть на класс JDate
в libraries/joomla/utilities/date.php видно, что конструктор требует два параметра – дату и часовой пояс. При сохранении даты нужно сделать следующее:
$date = new JDate($myDate, $myTimezone);
Теперь разберемся, как правильно вычислить часовой пояс. В этом также поможет Joomla. Напишем несложную служебную функцию, которая выглядит следующим образом:
/** * Возвращает пользовательскую временную зону (если она им установлена) * или установленную в конфигурации Joomla * * @return object DateTimeZone */ public static function getTimeZone() { $userTz = JFactory::getUser()->getParam('timezone'); $timeZone = JFactory::getConfig()->getValue('offset'); if ($userTz) { $timeZone = $userTz; } return new DateTimeZone($timeZone); }
В первой строчке указываем часовой пояс пользователя, во второй – устанавливаем глобальные настройки поясов. Если пользователь установил часовой пояс, передадим значение в объект DateTimeZone
. Если же пользователь не установил часовой пояс, будет работать глобальная настройка поясов. Имея правильный часовой пояс, можно отформатировать дату в MySQL и хранить в базе данных.
$myTimezone = myHelperClass:getTimezone();
$date = new JDate($myDate, $myTimezone)->format('Y-m-d H:i:s', false, false);
Первый параметр у функции форматирования - 'Y-m-d H:i:s
'. Это формат, в котором дата будет храниться в базе данных. Второй – указывает, что нужно отображать время в GMT/UTC. Третий параметр указывает функции на то, что дату не нужно переводить.
Теперь можно сохранить корректную дату UTC в базе данных. Давайте покажем дату пользователю. Но не повторяйте мою ошибку. Когда я пытался показать дату, хранимую в БД, я посчитал, что второй параметр, который нужно передать в JDate
– это часовой пояс. Я использовал служебную функцию и передал часовой пояс в качестве второго параметра. Далее, я вывел данные с помощью служебной операции, но к мооему удивлению, время отставало на два часа. Мне требовался часовой пояс Берлина - GMT+1 (и +1 для DST), но время имело вид -2. В последствии, я купил книгу Date and Time programming. Эта книга полезна детальной информацией об обсуждаемом предмете, а также будет интересна PHP разработчикам.
Я понял, что второй параметр должен помочь JDate
конвертировать дату в UTC, и нужно было передать параметр часового пояса, если время было в формате UTC. Вот, что для этого нужно:
$date = new JDate($myDate);
$date->setTimezone($myTimezone);
echo $date->format(...);
Все просто. Еще несколько полезных вещей:
JHtml::_('date', $myDate)
выводит автоматически дату UTC в формате пользователя и не нужно высчитывать ее самому.JHtml::_('calendar', myDate ...)
не конвертирует дату в формат пользователя, так что нужно самому настроить правильные часовые пояса.- При использовании календарного время в
JForm
, можно настроить фильтрSERVER_UTC
илиUSER_UTC
, который будет высчитывать часовые пояса.
Автор: Daniel Dimitrov