Unix Timestamps and Timezones
Updated: May 2026
A Unix timestamp has no timezone — it is an absolute count of seconds from the UTC epoch. And yet timezone bugs involving timestamps are among the most common defects in production software. The bugs live entirely in the conversion layer: when timestamps are created from local strings or displayed without an explicit timezone.
Free · No upload · Instant
The fundamental principle
A Unix timestamp is always UTC. The integer 1735689600 represents exactly one moment in history: January 1, 2025, 00:00:00 UTC. This moment corresponds to different local times depending on where you are: 19:00 on December 31, 2024 in New York; 01:00 on January 1, 2025 in Paris; 09:00 on January 1, 2025 in Tokyo.
The timestamp itself does not change. Only the display changes. Timezones are a display concern — they should be resolved as late as possible, ideally in the presentation layer.
The best architecture: store UTC timestamps in your database, pass timestamps between services, and apply timezone only when generating output for a specific user.
UTC offsets vs. IANA timezone names
There are two ways to express a timezone:
- UTC offset — a fixed offset from UTC:
+01:00,-05:00. Simple, but static. Does not account for Daylight Saving Time changes. Use only for historical records or fixed-offset requirements. - IANA timezone name — a named zone from the IANA tz database:
Europe/Paris,America/New_York,Asia/Tokyo. Encodes the full history of DST transitions for that region. Always prefer IANA names for user-facing timezone selection.
For example, America/New_York is UTC−5 in winter and UTC−4 in summer. Using the fixed offset -05:00 for a summer date would be wrong by one hour.
DST and timestamps
Daylight Saving Time transitions create two edge cases that require careful handling:
- Spring forward (gap) — Clocks jump forward one hour. Local times like
2025-03-09 02:30:00inAmerica/New_Yorkdo not exist. If you try to build a timestamp from that string in that timezone, runtimes handle the gap differently (some round forward, some backward). - Fall back (overlap) — Clocks repeat an hour. Local times like
2024-11-03 01:30:00inAmerica/New_Yorkoccur twice. Without DST flag disambiguation, the earlier (EDT) or later (EST) occurrence is ambiguous.
Unix timestamps have no DST ambiguity. A timestamp always maps to exactly one UTC instant. The ambiguity only exists in the local-time representation. This is another reason to store timestamps as integers and resolve local time at display.
Common timezone bugs in code
- Server timezone leaking into output.
new Date().toLocaleString()in Node.js ordate('Y-m-d')in PHP use the server's system timezone — which may differ from the user's. - Parsing a local string as UTC.
new Date('2025-01-01 00:00:00')in JavaScript is parsed as local time. Append aZor a+00:00suffix to force UTC. - Using a UTC offset instead of an IANA name for recurring events. A meeting scheduled at
09:00 Europe/Parisstays at 9 AM regardless of DST. A meeting at09:00 +01:00shifts by one hour in summer because the offset is wrong for CEST. - Storing formatted dates in the database. If you store
"2025-01-01 00:00:00"without a timezone, you lose the ability to correctly convert to another timezone later.
Best practices
- Store all timestamps as UTC integers or
TIMESTAMPTZin PostgreSQL. - Collect the user's IANA timezone name at registration; store it alongside their data.
- Apply the timezone only at the final rendering step — never in business logic.
- Always pass an explicit
timeZonetoIntl.DateTimeFormat,toLocaleString(), and equivalents. - Use ISO 8601 with explicit offset (
2025-01-01T01:00:00+01:00) when exchanging dates as strings between services. - Run your server in UTC (
TZ=UTC). This eliminates server-local-time bugs entirely.
The Flowfiles converter lets you verify a timestamp in any IANA timezone instantly — useful when debugging a timezone mismatch between environments.