Files
dev-conventions/arch/time.md
T
av 4a59c71737 заведён канон общих конвенций для личных проектов
- 13 конвенций по осям arch / lang / stack / common; репозитории берут
  оттуда копии в свой docs/conventions/ и коммитят их у себя
- conv — синхронизация копий: add / status / diff / pull / push, локальные
  регионы исключены из сравнения, поэтому расхождение не даёт шума
2026-07-25 18:18:18 +03:00

5.0 KiB

status
status
рекомендуемая

Время

Один формат времени на всё приложение: хранение, логи, API, обмен с внешними системами. Разные форматы в разных слоях — источник ошибок, которые всплывают через полгода на границе перехода на летнее время.

Формат

  • RFC 3339, UTC, суффикс Z: 2026-06-28T11:23:45Z.
  • Ширина фиксируется на каждый носитель и внутри него не плавает. Лексикографическая сортировка равна хронологии только среди строк одинаковой длины: …00.123Z сортируется раньше …00.12Z, хотя хронологически позже. Ради этого формат и фиксируется — ORDER BY created_at по текстовому полю обязан давать порядок событий.
  • Разные носители могут иметь разную точность: строки БД и строки лога между собой никогда не сравниваются. Требование — не «одна точность на приложение», а «внутри колонки и внутри потока логов ширина одна».
  • Локальное время не хранится и не передаётся нигде — ни в БД, ни в логах, ни в JSON API.

Генерирует приложение, а не хранилище

  • Единая точка получения «сейчас» и единая точка форматирования и разбора — как с идентификаторами (arch/db-identifiers.md). Прямые вызовы часов по коду не разбросаны: иначе ни формат, ни зона не гарантированы.
  • Дефолты в схеме БД не используем. Забытая вставка created_at должна падать громко, а не тихо получать значение от БД — иначе расходятся источник времени (сервер БД) и его формат.

Длительность — не метка времени

Измерение длительности операции — отдельная величина: число (обычно миллисекунды) в поле вида duration_ms, а не разность двух меток и не время в формате выше. Засекает её тот слой, который делает вызов.

Интервал измеряется монотонными часами процесса, а не вычитанием сохранённых меток: стенные часы подводит NTP, они могут шагнуть назад и дать отрицательную длительность. Из этого следует, что источник меток времени и источник интервалов — разные, даже если оба называются «часы».

Зоны

Единственное место, где появляется не-UTC, — отображение пользователю. Зона берётся из конфигурации (arch/config.md), значение по умолчанию — UTC. На хранение, сортировку и логи она не влияет.

Если бизнес-логика оперирует календарными сущностями («сегодня», «за месяц»), зона указывается явно в месте вычисления — молчаливое использование системной зоны процесса запрещено: она разная на ноутбуке и в контейнере. По умолчанию это та же зона, что и для отображения; если календарная логика требует другой, это записывается явно.

Конвенция описывает фиксацию свершившихся моментов. Планирование будущих событий — отдельный случай (там хранят локальное время плюс имя зоны, потому что правила зон меняются); пока такой сущности нет, правило не формулируем.

Связано

  • arch/config.md — где задаётся зона отображения.
  • arch/db-identifiers.md — то же правило «генерирует приложение» для id.