Reading a Unix Timestamp Without Getting the Wrong Day
A timestamp is a count, and the count is only meaningful once you know what it counts from and in what unit. This converter takes a number and shows you the moment it names, in four formats, plus the reverse direction. The number is easy to type; the two assumptions built into the page are what trip people.
Seconds or milliseconds: the page decides by length
The box's own placeholder says "seconds (10 digits) or milliseconds (13 digits)", and the implementation is exactly that — a character-length test. Anything with 13 digits or more is read as milliseconds; anything shorter is read as seconds.
That works because of where the digit boundaries fall:
| Value | Digits | Real moment |
|---|---|---|
| 1,000,000,000 seconds | 10 | 2001-09-09 01:46:40 UTC |
| 1,000,000,000,000 milliseconds | 13 | 2001-09-09 01:46:40 UTC |
| 10,000,000,000 seconds | 11 | 2286-11-20 |
Both scales crossed into their modern digit count at the same instant, 9 September 2001 — the day the billionth second was celebrated. Since then, a 10-digit value is seconds and a 13-digit value is milliseconds, and the length test is correct for anything in normal use.
Where it is wrong is also visible in that table. 11 and 12-digit values are always treated as seconds, and:
- A millisecond timestamp from before September 2001 has 12 digits or fewer.
100000000000(that is 1973-03-03 in milliseconds) gets multiplied by 1,000 and lands in year 5138. - Past November 2286, seconds become 11 digits and will be read as milliseconds.
So if a converted date looks absurdly far in the future or past, the first thing to check is not the tool — it is whether your source value was ever milliseconds with fewer than 13 digits. Multiply or divide by 1,000 yourself and re-enter.
Two related quirks of the same length rule:
- Negative values count their sign.
-170000000000is thirteen characters, so it is read as milliseconds and lands before 1970, as intended. Pre-1970 dates work:-1000000000seconds gives 1938-04-24. - The field is a number input, so it accepts exponent notation — and
1e12is four characters. It is read as seconds, multiplied, and reported as a date in the year 33658. Type digits, not shorthand.
Four outputs, and only two of them mean the same thing everywhere
Enter a valid timestamp and you get:
- UTC — formatted as an HTTP-style string ending in
GMT, precise to the second. Unambiguous anywhere. - Local Time — your machine's zone, with the zone name and offset spelled out. This is the line that disagrees between two people, and it is the usual cause of "the log says the 5th, my converter says the 4th".
- ISO 8601 — always UTC, ends in
Z, carries milliseconds. The right thing to paste into a bug report or another tool. - Readable — local time in a loose
2026-9-29 14:05:07 Tueshape. Note the month and day are not zero-padded, so this line does not sort as text. Do not use it as a key; use it to eyeball a date.
The underlying range is the JavaScript date range: ±8,640,000,000,000,000 milliseconds, roughly year ±275760. A value outside it produces no error at all — see below.
Nothing on this page will tell you the input was bad
This is the behaviour to remember. The conversion has no error path and no status message:
- Clearing the box resets all four lines to
--. That case is handled. - A number too large to become a date — twenty digits, or exponent notation that overflows — is accepted by the field, fails inside, and leaves the previous four results on screen with no change at all. The box shows your new value; the lines show the old moment. Two out-of-range inputs in a row look exactly like a converter that is ignoring you.
So treat "the results did not move" as the error signal. If a conversion seems stuck, clear the box, confirm the --, then enter a value you have checked by digit count.
The other tab: date in, timestamp out
The reverse direction uses the browser's date-and-time picker, and it has one limit worth knowing before you use its answer as a precise value.
The picker offers date, hour and minute — no seconds. So whatever you read out of it is minute-aligned: the seconds timestamp is always a multiple of 60, and the milliseconds value always ends in 000. It also opens pre-set to the current hour and minute, so on first load the number it shows is up to 59 seconds in the past.
That is fine for "roughly what epoch value is 3pm tomorrow" and wrong for "reproduce this log line". For exact seconds, work from the first tab, or grab the live clock.
The live clock at the top counts seconds and milliseconds, updating once per second — the fastest way to get "now". It has no copy button, and neither do the four outputs of the first tab; only the two timestamp fields on this second tab have Copy. Elsewhere, select the text and copy it manually.
Two facts that explain most timestamp arguments
Time zone is a display choice, not a property of the number. A Unix timestamp names an instant; 1700000000 is the same moment in Shanghai and in Berlin. What differs is the calendar date and clock time printed for it. If two people convert the same value and read different dates, neither is wrong — they are in different zones, and the boundary between days is what moved. Store and compare timestamps; format only at the edge, for a human.
Unix time ignores leap seconds. Every minute in this scale is exactly 60 seconds, even the minutes that astronomically contained a leap second. Timestamps are therefore consistent with each other — differences and orderings are fine — but they are not a perfectly uniform physical clock. It matters only if you are doing sub-second arithmetic across a leap-second boundary, and then it matters a great deal.
Does anything leave the page?
No. The conversion uses the Date object in your browser and the picker's own value; there is no request, no stored history, and no account. The live clock and all four formats come from your machine's clock and time-zone setting, which also means the page is only as correct as your system clock — if your device's time is wrong, its local formatting is wrong too.