Работя върху приложение на Rails, което съхранява всички дати в PostgreSQL като „TIMESTAMP WITHOUT TIME ZONE“. (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.06.2015 г. в 10:00 (Европа/Берлин). Но сега е лято, така че се прилага лятно часово време и 10:00 в „Европа/Берлин“ вече е 08:00 в UTC.
Поради това намирането на всички проекти, чиято продължителност е изтекла чрез използване на следната заявка, не работи за проекти, които започват/завършват извън границите на DST:
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, ако пресечете границата на лятното часово време по един или друг начин.
Благодаря много за всякакви съвети!