Проблемы с датировкой PHP при переходе на летнее время

StackOverflow https://stackoverflow.com/questions/385306

  •  23-08-2019
  •  | 
  •  

Вопрос

У меня возникла очень странная ошибка в каком-то имеющемся у меня PHP-коде.Страница предназначена для управления зачислением студентов на курсы.На странице представлена таблица курсов студента, и в каждой строке указано количество дат:когда они поступили, когда они закончили, когда они прошли оценку и когда они получили свой сертификат.

Данные таблицы генерируются PHP (извлекая данные из базы данных), а Javascript фактически визуализирует таблицу.Результатом работы PHP является JS-код, который выглядит примерно так:

var e = new Enrolment();
e.contactId = 5801;
e.enrolId = 14834;
e.courseId = 3;
e.dateEnrolled = new Date(1219672800000);
e.dateCompleted = new Date(-1000);  // magic value meaning they haven't completed.
e.resultDate = new Date(1223647200000);
e.certDate = new Date(1223560800000);
e.result = 95;
e.passed = true;
enrolments[14834] = e;

В базе данных все поля даты хранятся в виде DATE (не DATETIME) поля.

Ошибка заключается в том, что даты отображаются как один выходной.Я бы заподозрил, что это во многом связано с тем, что сервер находится в районе, где действует летнее время, тогда как здесь его нет (это означает, что серверное время отключено на один час).Это многое объясняет, особенно то, как подготовка данных и рендеринг выполняются в двух разных часовых поясах.Это:сервер сообщает клиенту, что пользователь завершил работу в полночь 15 августа, а клиент интерпретирует это как 11 вечера 14-го и, следовательно, отображает 14 августа.

Но вот что сбивает с толку:это делается только для полей resultDate и certDate!Я скопировал данные на свой локальный сервер и обнаружил, что рабочий сервер фактически отправляет другую временную метку (ту, которая отключена на 1 час) только для этих двух полей, тогда как поле dateEnrolled остается тем же самым.

Вот результат, использующий точно такой же код и данные из базы данных:

// local server (timezone GMT+1000)
e.dateEnrolled = new Date(1219672800000);   // 26 Aug 2008 00:00 +10:00
e.dateCompleted = new Date(-1000);
e.resultDate = new Date(1223647200000);     // 11 Oct 2008 00:00 +10:00
e.certDate = new Date(1223560800000);       // 10 Oct 2008 00:00 +10:00

// production server (timezone GMT+1100)
e.dateEnrolled = new Date(1219672800000);   // 26 Aug 2008 00:00 +10:00
e.dateCompleted = new Date(-1000);
e.resultDate = new Date(1223643600000);     // 10 Oct 2008 23:00 +10:00 **
e.certDate = new Date(1223557200000);       // 09 Oct 2008 23:00 +10:00 **

Я могу понять, была ли это проблема из-за того, что переход на летнее время не учитывался, но обратите внимание, что введенная дата одинакова?

PHP- код, который преобразует дату MySQL в временную метку unix, выглядит следующим образом:

list ($year, $month, $day) = explode ('-', $mysqlDT);
$timestamp = mktime (0,0,0, $month, $day, $year);

Есть какие-нибудь идеи о том, как это исправить?

Это было полезно?

Решение

Это потому, что вы используете mktime, который зависит от конкретной локали.То есть он преобразует его в количество секунд с 00:00: 00 1970-1-1 по Гринвичу, и это смещается на 1 час с одним часовым поясом.

Вы также должны помнить, что javascript использует тот же часовой пояс, что и браузер, а не веб-страница.

e.resultDate = new Date(year, month - 1, day);

Это гарантирует, что дата будет одинаковой для каждого зрителя из каждого часового пояса.

Или вы можете использовать gmmktime и использовать методы UTC в Date.

Другие советы

Хорошо, я только что понял, почему это портит одно свидание, но не другое.В августе переход на летнее время не действовал. мазок для лица

  1. всегда храните даты / datetimes в GMT / UTC
  2. внимательно посмотрите на запрос, который извлекает эти значения, есть что-нибудь отличающееся от тех, которые корректируются?
  3. если нет, то все ли они являются меткой времени, датой или datetime?

Скорее всего, это будет проблема экономии дневного света.Причина, по которой это делается только для resultDate и certDate, заключается в том, что dateEnrolled приходится на август, переход на летнее время обычно начинается / заканчивается в конце сентября или начале октября.

Установите параметр date.timezone ini в качестве часового пояса вашего приложения, используя apache.conf, .htaccess или ini_set().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top