toolhq.io

All posts
5 min readby Jameel Haider

ISO 8601 vs Unix time: which timestamp format to store

When you store a point in time, you usually choose between two representations: an ISO 8601 string like 2026-09-15T14:30:00Z or a Unix epoch integer like 1789821000. Both identify the same instant. The difference is in what they make easy and what they let you forget, and the right choice depends on who reads the value and what the code does with it.

What each one is

Unix time is a single integer counting seconds since the epoch, midnight UTC on 1 January 1970. 1789821000 is a count, nothing more. It is inherently in UTC because the epoch is defined in UTC, and it carries no time zone, no formatting, and no ambiguity about what it means.

ISO 8601 is a text format: YYYY-MM-DDTHH:mm:ss with an optional fractional second and a time zone designator. The trailing Z means UTC (Zulu time); an offset like +05:30 means the string is expressed in that offset from UTC. It is human readable and sorts correctly as plain text when the zone is consistent.

PropertyUnix timeISO 8601
Example17898210002026-09-15T14:30:00Z
Human readablenoyes
Carries zone infoalways UTC, implicityes, explicit
Arithmetictrivialneeds parsing
Sorts lexicallyyes (fixed width)yes (if zone consistent)
Sub-second precisionneeds conventionnative

Readability vs arithmetic

The core tradeoff is this: Unix time is for machines, ISO 8601 is for humans.

Unix time makes arithmetic trivial. The difference between two events is one subtraction; "five minutes from now" is + 300. There is no parsing, no locale, no month-length logic. Comparisons are integer comparisons. If your code mostly computes durations and ranges, integers are a pleasure to work with.

ISO 8601 makes inspection trivial. A human reading a log, a database row, or an API response sees the actual date and time without a conversion tool. That is worth a great deal during debugging, and it is why APIs and logs overwhelmingly use ISO strings. The cost is that every arithmetic operation requires parsing the string into a date object first.

The time zone question

This is the real decision point, and it is often misunderstood. Unix time has no time zone because it is always UTC; there is nothing to get wrong. ISO 8601 can carry a zone, which is both its strength and its risk.

A value like 2026-09-15T14:30:00Z is unambiguous: it is 14:30 UTC. But 2026-09-15T14:30:00 with no Z and no offset is a naive timestamp, and different systems guess differently about what zone it means. That guessing is the source of countless timestamp bugs. If you store ISO 8601, always include the offset or Z. A naive string is a defect waiting to happen.

Neither format should be used to store a wall-clock time that must stay fixed in a local zone, such as "9am in the office's city, whatever UTC that maps to on the day." For that you need the instant plus a named zone like America/New_York, because the UTC offset changes across daylight saving. Storing only an offset or only UTC loses the rule you actually meant.

Which to pick

  • Store Unix time when the value is internal, consumed mainly by code, and heavily used in arithmetic or range queries. It is compact, unambiguous, and fast to compare.
  • Store ISO 8601 with an explicit zone when humans will read it, when it crosses system boundaries as JSON or in logs, or when sub-second precision and self-description matter. Most databases also have a native timestamp type that stores the instant efficiently and renders ISO on read, which gives you both.
  • Always normalize to UTC at storage time regardless of format, and convert to local time only for display. A database full of mixed-zone values is far harder to reason about than one in a single reference frame.

A pragmatic default for application data is a UTC timestamp column that you read back as ISO. You get integer-like comparison from the engine and readable output for free.

To move between an epoch integer and a readable ISO 8601 string in either direction, and to confirm a value is the instant you think it is, paste it into the Timestamp Converter.