В интеграции передают время события без часового пояса. Какой дефект контракта нужно устранить?
Нужно явно зафиксировать семантику времени: передаётся ли абсолютный момент, локальные дата и время или календарная дата. Для абсолютного момента контракт должен включать часовой пояс или смещение, а потребители должны одинаково интерпретировать значение.
Иначе один сервис может считать событие произошедшим раньше или позже другого, что приводит к неверной сортировке, нарушению временных ограничений и расхождению данных.
Интеграционные контракты часто начинались с простых строковых полей, например даты или времени без дополнительного контекста. Такой формат казался достаточным внутри одной системы, где все компоненты использовали один часовой пояс.
При разделении системы на микросервисы сервисы могут работать в разных регионах, средах и часовых поясах. Поэтому значение времени стало не только форматом данных, но и частью бизнес-смысла контракта.
Значение вроде «2025-03-08 10:00:00» не отвечает на вопрос, в какой временной точке произошло событие. Это может быть 10:00 по Москве, по UTC или локальное время офиса пользователя.
Неоднозначность опасна, когда потребитель:
Даже если технический формат строки одинаков, бизнес-интерпретация может различаться. В результате контракт формально совместим, но семантически нарушен.
Сначала нужно определить тип передаваемого значения.
Абсолютный момент описывает единую точку на временной шкале: например, момент создания заказа или публикации события. Для него следует передавать UTC либо явное смещение часового пояса. Потребитель может преобразовать значение в локальное время только для отображения.
Локальные дата и время описывают время в конкретном месте или контексте, например «начало рабочего дня филиала». В этом случае одного смещения может быть недостаточно: контракту могут понадобиться идентификатор часового пояса и правило перехода на летнее время.
Календарная дата не является моментом времени. Дата рождения, дата закрытия отчётного периода или день поставки не должна автоматически преобразовываться в UTC, иначе при отображении в другом часовом поясе может измениться календарный день.
В контракте нужно зафиксировать не только представление значения, но и его смысл: допустимую точность, часовой пояс, правила округления и поведение при отсутствии значения. Изменение поля с локальной датой на абсолютный момент — это изменение семантики, даже если имя и строковый формат остались прежними.
Практическое правило: события и факты, которые нужно упорядочивать между сервисами, обычно должны содержать абсолютный момент. Бизнесовые даты и расписания следует моделировать отдельно, не подменяя их универсальным временем.
Сервис заказов публиковал время создания заказа как локальную строку без часового пояса. Сервис доставки сравнивал её со своим временем в UTC и иногда назначал заказ на неправильный интервал. Ошибка проявлялась только для клиентов из других регионов и была особенно заметна при переходе на летнее время.
Рассматривались три варианта:
Выбрали третий вариант. Сервис заказов стал публиковать момент создания как значение с явной временной зоной, а расписание доставки — как локальное время в контексте региона. После этого сортировка событий стала однозначной, а правила доставки перестали зависеть от часового пояса сервиса-потребителя.
Для абсолютного момента обычно достаточно передавать UTC, если контракт однозначно объявляет это правило. Однако UTC не решает задачу локального расписания или календарной даты: преобразование такой даты в UTC может изменить её смысл.
Кроме того, потребителю может понадобиться исходный часовой пояс для аудита или отображения. Поэтому выбор UTC должен следовать из семантики поля, а не быть механическим соглашением для всех временных значений.
Совместимость включает не только структуру и тип поля, но и его смысл. Если продюсер начинает передавать локальное время вместо абсолютного момента, потребитель может продолжить успешно читать строку, но принимать неверные решения.
Такое изменение является семантически несовместимым. Его нужно оформлять как изменение контракта: документировать новое значение, проверить потребителей и при необходимости использовать новую версию поля или события.
Фиксированное смещение, например «UTC+03:00», описывает положение относительно UTC в конкретный момент, но не всегда описывает правила региона на другие даты. Для будущего расписания нужен идентификатор часового пояса с правилами его изменений.
Также некоторые локальные времена могут не существовать или встречаться дважды при переводе часов. Контракт должен определить, как разрешаются такие случаи; иначе разные сервисы могут выбрать разные моменты для одного и того же локального значения.