Almost every system you use quietly agrees on one way of writing down time: a single number, counting seconds from a fixed midnight in 1970. It appears in databases, APIs, logs and tokens, usually unreadable at a glance — 1700000000 tells you nothing until you convert it. This guide explains what that number is, the unit trap that catches everyone, and the calendar edge cases (leap seconds, 2038, time zones) that make time the hardest “simple” problem in software. To convert a timestamp right now, use the timestamp converter.
The epoch and the count
Unix time counts the seconds elapsed since 1970-01-01 00:00:00 UTC — the Unix epoch. Nothing cosmic happened then; it was a round-ish, recent date when Unix was being built, later standardised by POSIX. A timestamp of 0 is that midnight; 86,400 is the next midnight; negative values count backwards into 1969 and earlier.
The design has two superpowers. First, it is universal: the number is the same everywhere on Earth, because it refers to an instant, not a wall-clock reading. Second, it makes arithmetic trivial — durations are subtractions, ordering is comparison, and “in 15 minutes” is +900. Every complexity of calendars (months of uneven length, leap years, daylight saving) is deferred to the moment a human looks at the value, which is exactly where it belongs.
Seconds, milliseconds and the eternal mix-up
Unix defines the count in seconds. But JavaScript’s Date.now() returns milliseconds, Java commonly uses milliseconds, some systems use microseconds (Go’s UnixMicro, many databases) or nanoseconds. The values are indistinguishable in form — just digits — and wrong by factors of a thousand:
| Value | Read as | Result |
|---|---|---|
| 1700000000 (seconds) | milliseconds | 1970-01-20 — everything looks like it just after the epoch |
| 1700000000000 (milliseconds) | seconds | the year 55840, or an overflow |
| 1700000000000000 (microseconds) | milliseconds | a date in 55840 again |
The practical check is digit count: at present, seconds have 10 digits, milliseconds 13, microseconds 16. Our converter detects the unit from the magnitude and states its assumption out loud, because a silent guess is how “expires at” fields end up in the wrong millennium. When an API gives you a mysterious timestamp, count digits before anything else.
What timestamps are not: time zones, UTC and GMT
A timestamp has no time zone. Time zones appear only when converting the instant to a local date and time for display — 1700000000 is 22:13:20 in London and 06:13:20 the next morning in Perth, the same instant wearing two presentations. This is why the correct pattern is: store the number, display the local time, and never store a local time without its zone.
UTC and GMT are often confused. GMT is a time zone (the civil time at Greenwich, and the basis of the UK’s winter time); UTC is the global time standard from which all zones are defined, maintained with atomic clocks. For almost all software purposes they read identically — which is why our converter’s “UTC” line uses the GMT label in its string, as browsers do — but UTC is the standard timestamps are anchored to. Treat “UTC” as the correct term in code and APIs, and GMT as its familiar face.
Leap seconds and the 86,400-second fiction
Real Earth days are not exactly 86,400 atomic seconds; leap seconds are occasionally inserted to keep UTC aligned with the planet’s rotation. Unix time ignores them: it defines every day as exactly 86,400 seconds, and when a leap second occurs, systems typically repeat, smear or step a second. The consequence is that Unix time is not a physically exact stopwatch since 1970 — it is a consistent numbering of civil seconds, which is all software needs. If you ever diff two timestamps across a leap second and are off by one, this is why.
The year 2038 problem
Stored in a signed 32-bit integer, seconds-since-epoch overflow at 2,147,483,647 — 2038-01-19 03:14:07 UTC — wrapping to a negative number read as December 1901. This is not theoretical: embedded systems, old file formats and legacy databases still carry 32-bit timestamps. 64-bit timestamps move the horizon to the year 292 billion, beyond any planning need. The millennium bug got the headlines; 2038 is the same bug with a longer fuse, and auditing for it is a real maintenance task in long-lived systems.
Working rules
- Store instants as timestamps (seconds, or milliseconds if you need the resolution — pick one per system and document it), never as unzoned local time strings.
- Interchange in ISO 8601 (
2023-11-14T22:13:20Z) when a human or another organisation must read the value; the string is unambiguous in a way a bare number is not. - Check units at every boundary — API responses, token claims (a JWT’s
expis seconds; see our JWT guide), database columns. - Convert to local time only for display, in the reader’s zone, at the last moment.
Time feels simple because clocks look simple. A Unix timestamp is the engineering answer to that illusion: one number, one reference point, no geography — and every hard problem pushed to the display layer, where a converter can solve it in the open.