All guides

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:

DigitsUnitExample (1 Jan 2025, 00:00 UTC)
10Seconds1735689600
13Milliseconds (1/1,000 s)1735689600000
16Microseconds (1/1,000,000 s)1735689600000000
19Nanoseconds (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 / systemTypical callUnit
Unix shelldate +%sSeconds
C / POSIXtime(NULL)Seconds
PHPtime()Seconds
Pythontime.time()Seconds (float, with fraction)
Python 3.7+time.time_ns()Nanoseconds
JavaScriptDate.now()Milliseconds
JavaSystem.currentTimeMillis()Milliseconds
Gotime.Now().Unix() / UnixMilli() / UnixNano()Seconds / ms / ns
PostgreSQLEXTRACT(EPOCH FROM now())Seconds (with fraction)
MySQLUNIX_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:

Conversions
seconds      = milliseconds / 1000
milliseconds = seconds * 1000
microseconds = milliseconds * 1000
nanoseconds  = microseconds * 1000

When 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 BigInt for 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.