Проблемы с датой в PHP при переходе на летнее время - PullRequest
0 голосов
/ 22 декабря 2008

У меня очень странная ошибка, возникающая в каком-то 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: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);

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

Ответы [ 5 ]

3 голосов
/ 22 декабря 2008

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

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

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

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

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

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

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

1 голос
/ 22 декабря 2008

Хорошо, я только что выяснил, почему это испортило одно свидание, а не другое. Летнее время в августе не действовало. Facepalm

0 голосов
/ 22 декабря 2008

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

...