Nanoseconds to date
Convert nanoseconds to human readable date. Enter timestamp in nanoseconds (e.g. 1704067200000000000).
A nanosecond timestamp in a JavaScript number silently loses its last three digits
JavaScript numbers hold integers exactly only up to 2⁵³ − 1. A current nanosecond timestamp is about 1.77 × 10¹⁸, which exceeds that limit by a factor of 196. Feed one in and 1770000000123456789 comes back as 1770000000123456800 — no error, no warning, just three digits quietly replaced.
How it works
- Converts nanosecond timestamps to dates and back, keeping the sub-millisecond part intact.
- Flags the precision limit, because the failure is silent rather than loud.
- Handles the conversion to milliseconds that most date libraries require as input.
nanoseconds ÷ 1,000,000 = milliseconds nanoseconds ÷ 1,000,000,000 = seconds MAX_SAFE_INTEGER = 9,007,199,254,740,991 (2⁵³ − 1) in nanoseconds that whole range spans only ~104 days in milliseconds it spans ~285,000 years
Worked example
What each time unit buys inside the safe integer range, and what happens when you exceed it.
- milliseconds: 2⁵³ covers about 285,000 years
- microseconds: about 285 years
- nanoseconds: about 0.285 years — roughly 104 days
- 1770000000123456789 assigned to a number
- reads back as 1770000000123456800
The last three digits changed and nothing reported it. A nanosecond timestamp needs BigInt or a string; storing it in an ordinary number is not a rounding inconvenience but a guarantee that sub-microsecond detail is fiction.
Reading the result
- Use BigInt for nanosecond arithmetic and convert to a number only after dividing down to milliseconds. The division must happen in BigInt space — converting first and dividing after has already destroyed the digits you were trying to keep.
- Databases and wire formats often carry nanoseconds as strings for exactly this reason. Parsing such a string into a float to 'clean it up' is the most common way the precision is lost, and it happens in the layer nobody inspects.
- JavaScript Date itself is millisecond-based and cannot represent sub-millisecond time at all. Converting nanoseconds to a Date discards the remainder by design, so the loss there is expected rather than a bug — the surprise is only when it happens silently during arithmetic.
- Nanosecond precision is rarely the real requirement. Log ordering, tracing and profiling usually need monotonic ordering rather than absolute nanosecond accuracy, and a monotonic clock delivers that without the representation problem.
Common questions
- Why did my timestamp change by a few hundred nanoseconds?
- It was stored in a floating-point number that cannot represent it. Above 2⁵³ − 1 integers are rounded to the nearest representable value, so 1770000000123456789 becomes 1770000000123456800. Nothing raises an error because this is defined behaviour, not a fault.
- How should nanosecond timestamps be stored?
- As BigInt in JavaScript, as a 64-bit integer in most other languages, or as a string when crossing a boundary such as JSON. Convert to a number only after you have divided down to milliseconds and no longer need the extra digits.