Seconds, milliseconds, microseconds or nanoseconds? How to tell which timestamp you have
Updated
All Unix-style timestamps count from the same instant — 1970-01-01 00:00:00 UTC — but they don’t all count in the same unit. The same moment can appear as 1735689600, 1735689600000, 1735689600000000 or 1735689600000000000. Read one in the wrong unit and you get a date in 1970 or tens of thousands of years in the future.
The quick rule: count the digits
For any date between 2001 and 2286, the number of digits tells you the unit immediately:
| Digits | Unit | Example (1 Jan 2025, 00:00 UTC) |
|---|---|---|
| 10 | Seconds | 1735689600 |
| 13 | Milliseconds (1/1,000 s) | 1735689600000 |
| 16 | Microseconds (1/1,000,000 s) | 1735689600000000 |
| 19 | Nanoseconds (1/1,000,000,000 s) | 1735689600000000000 |
The 10-digit window runs from 1,000,000,000 (9 September 2001) until 9,999,999,999 (20 November 2286), so for any present-day timestamp the rule holds. Older dates have fewer digits — a seconds timestamp from 1990 is nine digits long — which is why the converter uses magnitude ranges rather than an exact digit count to auto-detect the unit.
Who uses which unit?
| Language / system | Typical call | Unit |
|---|---|---|
| Unix shell | date +%s | Seconds |
| C / POSIX | time(NULL) | Seconds |
| PHP | time() | Seconds |
| Python | time.time() | Seconds (float, with fraction) |
| Python 3.7+ | time.time_ns() | Nanoseconds |
| JavaScript | Date.now() | Milliseconds |
| Java | System.currentTimeMillis() | Milliseconds |
| Go | time.Now().Unix() / UnixMilli() / UnixNano() | Seconds / ms / ns |
| PostgreSQL | EXTRACT(EPOCH FROM now()) | Seconds (with fraction) |
| MySQL | UNIX_TIMESTAMP() | Seconds |
The pattern to watch for is data that crosses a boundary: a JavaScript front end sending milliseconds to a Python or PHP back end that expects seconds, or a Go service writing nanoseconds into a column another team reads as milliseconds.
Converting between units
Each step is a factor of 1,000:
seconds = milliseconds / 1000
milliseconds = seconds * 1000
microseconds = milliseconds * 1000
nanoseconds = microseconds * 1000When going to a coarser unit, decide deliberately whether to round or truncate. Truncating (flooring) is the usual convention — Math.floor(Date.now() / 1000) in JavaScript — because it never moves a moment into the next second.
Watch out for precision loss
JavaScript numbers (and JSON numbers parsed by most JavaScript code) are 64-bit floating point, which can only represent integers exactly up to 253 − 1, or 9,007,199,254,740,991. A current nanosecond timestamp is around 1.7 × 1018 — well past that limit — so it silently loses its last few digits when parsed as a plain number.
- Send nanosecond and microsecond timestamps as strings in JSON if a JavaScript client will read them.
- In JavaScript, use
BigIntfor exact arithmetic:BigInt("1735689600000000000") / 1000000n. - Seconds and milliseconds are always safe; the limit only bites at microsecond and nanosecond resolution.
Symptoms of a unit mix-up
- A date in January 1970: you read seconds as milliseconds (the value is 1,000× too small for the unit you assumed).
- A date tens of thousands of years from now, or an “invalid date”: you read milliseconds as seconds.
- Durations off by exactly 1,000×: two values in different units were subtracted.