Прочитав замечательную статью Переезд временной зоны MSD в MSK — новый Y2K локального масштаба пару недель назад, проверили ОС на серверах и на этом успокоились, да не тут-то было. Сегодня с удивлением обнаружил, что время, показываемое PHP-скриптами на сервере, отстаёт от реального на один час.
Стали разбираться — оказалось, что не обновлённый своевременно PHP не зависит от системной библиотеки временных зон и по-прежнему считает, что Europe/Moscow соответствует UTC+3 вместо правильных UTC+4. Пока собирали новую версию, пришлось временно установить зону в Asia/Baku. Это вскрыло определённые проблемы, корень зла которых можно сформулировать одним предложением:
Хранить время в int (в формате unix timestamp) — зло!
Это удобно (по крайней мере, в PHP+MySQL), компактно, и так сложилось исторически, но сегодня я пожинал плоды и плевался. Дело в том, что сохраняя даты будущих событий в записях БД, которые попадали на время, позднее чем Oct 30 03:00:00 MSK 2011 (1319929200), PHP честно полагал, что мы переведём часы и надо добавить лишние 3600 секунд. И причина здесь не только в том, что мы не обновили PHP своевременно — да, это бы уменьшило последствия, но данные, сохранённые на будущее до этого так и остались бы неправильными. В результате в БД накопилось приличное количество данных, которые в один момент стали сдвинуты во времени на час вперёд.
Костыли в виде перевода зоны на Asia/Baku привели к тому, что время всех событий из БД стало отображаться на час больше, после обновления PHP и возврата к Europe/Moscow время позже сегодняшних 3 ночи стало показываться сдвинутыми на час позже, а до этого момента — нормально. Пришлось спешно писать кучу SQL-запросов для вычитания 3600 секунд из всех дат, которые позже 1319929200.
Что характерно, подобная беда накрыла не только нас — у коллег, разрабатывающих на .NET, я обнаружил ровно то же самое (часть дат позже сегодняшней ночи ушли на час вперёд), хотя время они хранят в UTC. У нас же в порядке остались только времена в формате datetime (timestamp не использовали).
Подозреваю, что завтра следует ожидать обнаружения довольно больших проблем (по крайней мере, если +1 час критически важен и сегодня никто не спохватился) во всех сервисах, где были сохранены даты в будущем в формате int (либо где забыли обновить базу временных зон &mdash к пример, у меня в Android по-прежнему Москва это +3, пришлось сделать Баку, чтобы обновление времени по NTP сработало как следует).
Стали разбираться — оказалось, что не обновлённый своевременно PHP не зависит от системной библиотеки временных зон и по-прежнему считает, что Europe/Moscow соответствует UTC+3 вместо правильных UTC+4. Пока собирали новую версию, пришлось временно установить зону в Asia/Baku. Это вскрыло определённые проблемы, корень зла которых можно сформулировать одним предложением:
Хранить время в int (в формате unix timestamp) — зло!
Это удобно (по крайней мере, в PHP+MySQL), компактно, и так сложилось исторически, но сегодня я пожинал плоды и плевался. Дело в том, что сохраняя даты будущих событий в записях БД, которые попадали на время, позднее чем Oct 30 03:00:00 MSK 2011 (1319929200), PHP честно полагал, что мы переведём часы и надо добавить лишние 3600 секунд. И причина здесь не только в том, что мы не обновили PHP своевременно — да, это бы уменьшило последствия, но данные, сохранённые на будущее до этого так и остались бы неправильными. В результате в БД накопилось приличное количество данных, которые в один момент стали сдвинуты во времени на час вперёд.
Костыли в виде перевода зоны на Asia/Baku привели к тому, что время всех событий из БД стало отображаться на час больше, после обновления PHP и возврата к Europe/Moscow время позже сегодняшних 3 ночи стало показываться сдвинутыми на час позже, а до этого момента — нормально. Пришлось спешно писать кучу SQL-запросов для вычитания 3600 секунд из всех дат, которые позже 1319929200.
Что характерно, подобная беда накрыла не только нас — у коллег, разрабатывающих на .NET, я обнаружил ровно то же самое (часть дат позже сегодняшней ночи ушли на час вперёд), хотя время они хранят в UTC. У нас же в порядке остались только времена в формате datetime (timestamp не использовали).
Подозреваю, что завтра следует ожидать обнаружения довольно больших проблем (по крайней мере, если +1 час критически важен и сегодня никто не спохватился) во всех сервисах, где были сохранены даты в будущем в формате int (либо где забыли обновить базу временных зон &mdash к пример, у меня в Android по-прежнему Москва это +3, пришлось сделать Баку, чтобы обновление времени по NTP сработало как следует).