Ir al contenido

ADR-015 — Datetime: UTC Storage, Browser-Local Computation and Display

ADR-015 — Datetime: UTC Storage, Browser-Local Computation and Display

Sección titulada «ADR-015 — Datetime: UTC Storage, Browser-Local Computation and Display»

Accepted

The stack stores and transmits datetimes in UTC (USE_TZ=True, ISO 8601 Z suffix). There was no explicit rule for which timezone the frontend uses for temporal logic. A bug exposed this: isLateHour() used getUTCHours() while display showed browser local time — the user saw “19:40” flagged as out-of-hours because the logic evaluated 22:40 UTC.

The user’s browser timezone is the sole basis for all computation and display in the frontend.

Stack layers.

LayerRule
Django/PostgreSQLUSE_TZ = True. Every DateTimeField persisted in UTC.
DRF / APISerializes ISO 8601 UTC with Z. No local offset accepted or returned.
Angular (display)Converts UTC to browser-local time (toLocaleString, toLocaleDateString, toLocaleTimeString).
Angular (logic)All temporal evaluation: browser-local methods (getHours(), getDay(), getDate()). Never getUTCHours() or any UTC variant.
Mock dataUTC with Z. Browser converts at render time, same as real API data.

Clarification — Z and +00:00 are both valid. Both are valid ISO 8601 UTC representations. The API uses Z (per [[api-conventions|docs/stack/api-conventions.md]]), but the frontend must accept either. new Date("...Z") and new Date("...+00:00") produce the same instant — no special handling needed.

Cardinal rule.

[!important] If the user sees a time on screen, any logic that evaluates that time must operate in the same timezone as the display.

Future timezone override. If a user needs a timezone different from their browser’s, implement as a user preference (profile setting), not a global convention change.

  • All temporal logic in Angular uses local Date methods (getHours, getDay, getDate, getMonth), never UTC variants.
  • Display and logic are always in sync — what the user sees is what the code evaluates.
  • Frontend tests involving times must account for the timezone of the machine running them.
  • Django/API unchanged: UTC remains the transport and storage format.
  • Mock data stays UTC with Z; browser converts identically to real API data.