В SQL существует большой набор функций для работы с датами и интервалами: DATEDIFF, DATEADD (T-SQL), работа с типом INTERVAL (PostgreSQL), функционал по переводам времен в разные зоны (AT TIME ZONE). Для корректной работы с датами ключевое — использовать типы данных с учетом временной зоны (TIMESTAMP WITH TIME ZONE, timestamptz), а не просто DATE или DATETIME, особенно для глобальных сервисов.
В разных СУБД синтаксис и особенности работы различаются:
DATEDIFF, DATEADD, FORMAT, но нет полноценного INTERVAL. Временные зоны регулируются явно.Ошибки часто возникают из-за несогласованности хранения в UTC/локальном времени и смешения операций, не учитывающих разницу.
SELECT EXTRACT(EPOCH FROM (event_end AT TIME ZONE 'UTC' - event_start AT TIME ZONE 'UTC')) / 3600 AS hours FROM events
Может ли разница дат в DATEDIFF дать отрицательное число, и что означает их порядок следования?
Ответ: Да, DATEDIFF (DATEDIFF(day, d1, d2)) возвращает отрицательное число, если d2 < d1. Важно не перепутать порядок параметров: сначала идет единица измерения, потом начальная дата, потом конечная.
Пример:
SELECT DATEDIFF(day, '2024-05-01', '2024-04-25') -- вернёт -6
История
В проекте с глобальными пользователями отчеты строились по локальному времени серверов в каждом регионе. Итог — разъезжающиеся агрегаты по датам и появление "дыр" на границе суток для пользователей из других часовых поясов. Исправлено переводом всех временных данных к UTC и пересчетом только для отображения.
История
При подсчете длительности подписки через DATEDIFF перепутали порядок дат. В результате некоторых пользователей ошибочно признали "сверхпользователями" с заведомо отрицательной давностью. Исправлено введением проверки порядка дат.
История
Разработчик хранил DATETIME без учета временной зоны, при миграции на PostgreSQL значения оказались интерпретированы как UTC, хотя исходно были в GMT+3, что привело к сдвигу событий в отчетах на 3 часа назад. Вывод — всегда хранить и преобразовывать даты с учетом зоны!