Проблемы с преобразованием даты и времени в PHP, связанные с переходом на летнее время - PullRequest
0 голосов
/ 12 ноября 2018

В моем веб-приложении есть некоторые функции локализации (предоставляемые через Ajax), которые позволяют пользователям отображать некоторую информацию о дате и времени в своем собственном часовом поясе, а также часовой пояс, относящийся к местоположению объекта, к которому в первую очередь относятся данные.

В результате некоторого тестирования я обнаружил, что, хотя мой код способен точно преобразовывать значения даты / времени, полученные из БД (т.е. включая корректировки DST), код не будет вычислять правильные смещения, когда я использую предоставленные даты в форме. Лучшее, чего мне удалось добиться, - это преобразовать значение даты / времени формы в UTC, но применяется неправильное смещение. Это означает, что мне нужно проверить, попадает ли дата в диапазон перехода на летнее время, и если это так, вернуть значение datetime на час. Это выглядит ужасно, и я буду признателен, если кто-нибудь знает, где я ошибся:

Пример:

  • Входное значение от 25/11/2018 16:00 NZDT (Pacific / Auckland) = UTC + 13
  • Выходное значение должно быть 25/11/2018 14:00 ADT (Австралия / Сидней) = UTC + 11
  • Если я извлекаю исходное значение из базы данных и затем конвертирую, тогда вычисления работают нормально, никаких проблем
  • Если я использую предоставленное в форме значение (которое мне нужно проверить, если пользователь обновил значение, не сохраняя его), произойдет следующее:

  • ОТ DB1 = 2018-11-25 03:00:00 (значение в DB, ​​в UTC)

  • ИЗ ФОРМЫ1 = 25/11/2018 16:00 (необработанное значение из формы)
  • FROM FORM2 = 2018-11-25 04:00:00 (изменения в UTC-12, т.е. NZST), что неверно, должно быть таким же значением, как DB1, то есть UTC-13, которое является смещением от NZDT обратно к UTC)
  • ОТ ФОРМЫ3 = 2018-11-25 03:00:00 (исправлено, как только я проверяю, попадает ли значение даты / времени в диапазон летнего времени)

Код следует:

echo "FROM DB1:  ".$getListing['lo_deadline']."<BR />";
echo "FROM FORM1:".$in_lo_deadline."<BR />";
$frmDateTime =  DateTime::createFromFormat($this->view->user->user_datetimeformat, $in_lo_deadline,new DateTimeZone($list_tmzn));                   
echo "FROM FORM2:".$frmDateTime->format('Y-m-d h:i:s')."<BR />";
//If $frmDateTime is in daylight savings then subtract an hour to arrive at the correct UTC value                   
if ($frmDateTime->format('I'))
{
    date_sub($frmDateTime, date_interval_create_from_date_string('1 hours'));
}
echo "FROM FORM3:".$frmDateTime->format('Y-m-d h:i:s')."<BR />";                    
$dates['set_dead'] = convertUserDate($frmDateTime->format('Y-m-d h:i:s'), $this->view->user->user_datetimeformat, $user_tmzn,'UTC');

1 Ответ

0 голосов
/ 13 ноября 2018

Что я понимаю из вашего кода, причина, по которой он показывает 2018-11-25 04:00:00, заключается в формате AM / PM. Вы должны использовать заглавную H вместо h в своем коде.

Вам необходимо понять разницу между 24-часовым и 12-часовым форматами. 2018-11-25 04:00:00 в соответствии с вашим форматом в формате AM / PM или 12-часовом формате, но в 24-часовом формате оно должно быть 2018-11-25 16:00:00. Время базы данных всегда в 24-часовом формате.

Изменение

$frmDateTime->format('Y-m-d h:i:s')

до

$frmDateTime->format('Y-m-d H:i:s')

Примечание: Вам не нужно вручную вычитать час, чтобы рассчитать переход на летнее время, поскольку php делает это автоматически.

...