ПрограммированиеBackend разработчик, BI-аналитик

Объясните, как обрабатывать временные данные и интервалы дат в SQL, в чем особенности функций работы с временем (DATEDIFF, DATEADD, INTERVAL) в разных СУБД? Какие ловушки могут встретиться при работе с часовыми поясами? Приведите пример корректного расчета разницы во времени.

Проходите собеседования с ИИ помощником Hintsage

Ответ

В SQL существует большой набор функций для работы с датами и интервалами: DATEDIFF, DATEADD (T-SQL), работа с типом INTERVAL (PostgreSQL), функционал по переводам времен в разные зоны (AT TIME ZONE). Для корректной работы с датами ключевое — использовать типы данных с учетом временной зоны (TIMESTAMP WITH TIME ZONE, timestamptz), а не просто DATE или DATETIME, особенно для глобальных сервисов.

В разных СУБД синтаксис и особенности работы различаются:

  • SQL Server: DATEDIFF, DATEADD, FORMAT, но нет полноценного INTERVAL. Временные зоны регулируются явно.
  • PostgreSQL: поддержка INTERVAL, множество функций (+/- INTERVAL), прямое управление зонами времени.

Ошибки часто возникают из-за несогласованности хранения в UTC/локальном времени и смешения операций, не учитывающих разницу.

Пример расчета разницы (PostgreSQL)

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 часа назад. Вывод — всегда хранить и преобразовывать даты с учетом зоны!