Skip to main content
time

Time zones are a lie: handle them as data in code

Store instants in UTC, retain the user or business IANA timezone, and convert at the boundary where people read or schedule time.

Thien Nguyen
By Thien Nguyen
Updated April 4, 2026 · 1 min read

Store a timestamp as an instant, such as 2026-04-04T01:30:00Z, and store the relevant IANA zone separately, such as Australia/Sydney. Do not store only “9am local”: daylight-saving transitions make that phrase ambiguous or impossible.

Model the question you are answering

Domain questionPersistDisplay / execute
When did an event happen?UTC instantConvert to viewer's zone
When should a meeting recur?Local rule + IANA zoneResolve each occurrence
What was the original wall time?Instant + originating zoneKeep both for audit
new Intl.DateTimeFormat('en-AU', {
  timeZone: 'Australia/Sydney', dateStyle: 'medium', timeStyle: 'short'
}).format(new Date('2026-04-04T01:30:00Z'));

Test the awkward hours

When clocks move forward, some local times never occur. When they move back, one local time occurs twice. A scheduler must define which instant it means; silently using the server's zone is not a definition.

An offset like +10:00 is not a timezone. It does not encode the future daylight-saving rules for Sydney, New York, or any other place.

Use IANA names in APIs and database records, display a zone label beside deadlines, and add tests around a transition for every recurring local-time feature. Time zones stop being mysterious once the model carries both the instant and the human rule that produced it.

References

Primary documentation and specifications checked when this article was last updated.

timedatabasesinternationalization

Related articles

All articles