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

У меня возникла очень странная ошибка в некотором коде 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 августа, а клиент интерпретирует это как 23:00 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 **

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

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

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

Есть идеи, как это исправить?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
3 661
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

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

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

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

Ответ принят как подходящий

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

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

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

Это обеспечит одинаковую дату для всех зрителей во всех часовых поясах.

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

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