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

75 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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`. На хранение, сортировку и логи она не влияет.
Если бизнес-логика оперирует календарными сущностями («сегодня»,
«за месяц»), зона указывается **явно** в месте вычисления — молчаливое
использование системной зоны процесса запрещено: она разная на ноутбуке и в
контейнере. По умолчанию это та же зона, что и для отображения; если
календарная логика требует другой, это записывается явно.
Конвенция описывает фиксацию **свершившихся моментов**. Планирование
будущих событий — отдельный случай (там хранят локальное время плюс имя
зоны, потому что правила зон меняются); пока такой сущности нет, правило не
формулируем.
<!-- local:механизировано -->
<!-- /local -->
<!-- local:отступления -->
<!-- /local -->
## Связано
- `arch/config.md` — где задаётся зона отображения.
- `arch/db-identifiers.md` — то же правило «генерирует приложение» для id.
<!-- local:связано -->
<!-- /local -->