Reading an epoch number
A Unix timestamp converter exists because 1757000000 is unreadable and 1757000000000 is
unreadable in a way that also happens to be wrong by a factor of a thousand. Paste either into the
box above and you get the instant it names, written six ways: the epoch in seconds, the epoch in
milliseconds, ISO 8601, RFC 2822, UTC, and the wall clock of whatever time zone your browser is set
to. Switch the direction and a date goes back the other way.
Everything runs in the page. Timestamps from production logs are often the only thing in a support ticket that identifies a customer, so nothing here is uploaded.
The factor-of-a-thousand mistake
The two conventions live side by side and neither is labelled. C, Go, Python, PostgreSQL and the
date command count seconds. JavaScript, Java and most JSON produced by a browser count
milliseconds. The moment a value crosses a language boundary, someone divides or fails to.
The symptom is unmistakable once you have seen it: a record dated January 1970 means seconds were
read as milliseconds, and a record dated in the year 57647 means milliseconds were read as seconds.
The tool guesses by magnitude — anything with twelve or more digits has to be milliseconds, because
1e11 seconds is the year 5138 — and then tells you what it assumed. A decimal point forces seconds,
because time.time() and microtime(true) are the only common sources that produce fractions.
If the guess is wrong, override it. A timestamp from 1971 genuinely is a small number, and no heuristic can tell it apart from a modern millisecond value cut short.
2038, and who still needs to care
The famous ceiling is not the epoch's fault; it is the width of the field holding it. A signed 32-bit integer stops at 2,147,483,647, which arrives at 03:14:07 UTC on 19 January 2038 and then wraps to 1901. Modern languages moved to 64-bit values long ago, and this page is unaffected because JavaScript numbers hold whole integers well past the age of the universe.
What is still exposed: embedded firmware compiled against a 32-bit time_t, file formats that
committed to four bytes, and database columns someone declared as INT because it was the obvious
type in 2008. Any of those handling a date in the future — a mortgage end date, a certificate
expiry, a retention policy — reaches the ceiling long before 2038 does.
Time zones, and why storage is a different question
The number itself has no time zone. That is the property worth protecting: it is a count of seconds from a fixed instant, so it means the same thing on every machine that reads it.
Local time is a rendering decision, and it depends on two things that both change: the reader's zone,
and the daylight saving rule that applied on that specific date. Britain moved its clocks forward on
29 March 2026, so the same wall-clock reading of 12:00 on the 28th and the 29th describes instants
an hour apart. The converter applies the rule for the date in question rather than the offset in
force today, which is the difference between a converter and a subtraction.
Store UTC, or store the epoch integer, and convert at the edge. Storing local time throws away the
offset and the offset is the part you cannot reconstruct: an hour written during the autumn
changeover happens twice, and nothing in the stored value says which one it was. When the local
reading genuinely matters — a meeting that must stay at 09:00 after the clocks change — store the
IANA zone name next to the instant, not the offset. Zones get new rules; Europe/London survives
them and +01:00 does not.
Working with the same log lines in another shape? The JSON to YAML converter
handles the config files these services read, and the case converter turns
created_at into createdAt when the API on the other side disagrees about spelling.