Я работаю над приложением Rails, которое хранит все даты в PostgreSQL как «TIMESTAMP БЕЗ ЧАСОВОГО ПОЯСА». (Rails обрабатывает часовой пояс на уровне приложения, которым для этого приложения является «Европа / Берлин».) К сожалению, переход на летнее время (DST) становится проблемой.
В упрощенной таблице «проекты» есть следующие столбцы:
started_at TIMESTAMP WITHOUT TIME ZONE
duration INTEGER
Проекты начинаются с started_at
и выполняются duration
дней.
Теперь предположим, что есть только один проект, который начинается 01.01.2015 в 10:00. Поскольку сейчас "Европа / Берлин" и сейчас январь (без летнего времени), запись в базе данных выглядит следующим образом:
SET TimeZone = 'UTC';
SELECT started_at from projects;
# => 2015-01-01 09:00:00
Он должен закончиться 30 июня 2015 года в 10:00 (Европа / Берлин). Но сейчас лето, поэтому применяется летнее время, и 10:00 в «Европе / Берлине» теперь 08:00 по всемирному координированному времени.
Из-за этого поиск всех проектов, для которых истек срок действия, с помощью следующего запроса не работает для проектов, которые начинаются / заканчиваются за пределами границ летнего времени:
SELECT * FROM projects WHERE started_at + INTERVAL '1 day' * duration < NOW()
Я предполагаю, что было бы лучше, если бы указанное выше WHERE выполняло расчет в часовом поясе «Европа / Берлин», а не в «UTC». Я пробовал несколько вещей с ::TIMESTAMTZ
и AT TIME ZONE
, ни один из них не работал.
В качестве примечания: согласно документам PostgreSQL, + INTERVAL
должен работать с интервалами «1 день» иначе, чем с интервалами «24 часа», когда дело касается летнего времени. При добавлении дней летнее время игнорируется, поэтому 10:00 всегда остается 10:00. С другой стороны, при добавлении часов 10:00 может стать 09:00 или 11:00, если вы тем или иным образом пересекаете границу летнего времени.
Большое спасибо за любые подсказки!