What a Unix timestamp counts
A Unix timestamp is the number of seconds that have elapsed since
1970-01-01T00:00:00Z, a moment called the Unix epoch. The trailing
Z matters: the epoch is defined in UTC. A timestamp is therefore not a “time in some
place”; it marks one exact worldwide instant. When you see 1700000000, it means
“exactly 1,700,000,000 seconds after that reference moment”.
Because it is a single number, a timestamp is the standard currency for APIs, logs and databases: it sorts naturally, has no formatting ambiguity, and no time zone attached to confuse things.
Seconds vs milliseconds: the classic trap
Two conventions coexist, and mixing them up is the most common timestamp bug:
-
Seconds: 10 digits today (e.g.
1700000000). Used by Unix tooling, many databases and most REST APIs. -
Milliseconds: 13 digits today (e.g.
1700000000000). Used by Java, JavaScript (Date.now()), .NET and most web platforms.
A quick sanity check: timestamps in seconds are currently around 1.7 × 10⁹; in
milliseconds around 1.7 × 10¹². If a “converted” date lands in 1970, you fed seconds
into a milliseconds parser; if it lands in the year 56,000, you did the opposite. Feeding one into
the other multiplies or divides by 1,000, creating about 16.7 minutes of error per misplaced digit.
Converting by hand (the mental model)
- Decide the unit. Count digits or compare against
1.7 × 10¹². - Convert to milliseconds if needed (seconds × 1000).
- Read the value as an offset from
1970-01-01T00:00:00Z; this gives the UTC date and time. - Apply a time-zone offset only if you want to see the same instant as a wall time somewhere else.
Step 3 always produces UTC; step 4 is where “the same moment” becomes “17:00 in Tokyo, 09:00 in London”. Conflating those two steps is the second most common timestamp bug.
Negative timestamps and the range
Timestamps before 1970 are negative: -1 is one second before the epoch
(1969-12-31 23:59:59 UTC). JavaScript’s Date supports ±8.64 × 10¹⁵ ms (roughly years
−271,821 to 275,760), which is far wider than any practical need. Values outside a tool’s stated
range should be rejected, not silently wrapped.
Doing it in code
In JavaScript and TypeScript the whole round trip is three expressions:
Date.now(): current time as epoch milliseconds.new Date(ms): timestamp → Date object; then.toISOString()for a UTC string.Math.floor(ms / 1000): milliseconds → whole seconds (floor, not round: truncating toward zero corrupts pre-1970 values by a second).
Going the other way, Date.parse('2026-10-28T14:30:00Z') parses an ISO string with an
offset into milliseconds. Strings without an offset are interpreted by implementation
rules; historically date-only strings were treated as UTC and date-times as local, which is
exactly the kind of ambiguity worth avoiding by always writing the offset.
Where this site helps
The Unix Timestamp to Date converter auto-detects the unit and states which one it used; Date to Unix Timestamp resolves your wall time in any IANA zone (daylight saving included); and Current Unix Timestamp shows live values you can copy. Everything runs locally in your browser; the timestamps you paste never leave the page.