Dev.to WebDev 🛠 Dev 👁 0 📖 2 min read

Is this timestamp in seconds or milliseconds? Guessing the unit from the digit count

You paste 1700000000 into a date converter and get November 2023. You paste 1700000000123 and get the same day, but only if the tool knows the second number is milliseconds. Feed that value to code that expects seconds a

You paste 1700000000 into a date converter and get November 2023. You paste 1700000000123 and get the same day, but only if the tool knows the second number is milliseconds. Feed that value to code that expects seconds and you get a year about 53,000 years from now. Feed the first value to new Date() and you get January 1970.

new Date(1700000000 * 1000).toISOString() // "2023-11-14T22:13:20.000Z"
new Date(1700000000).toISOString()        // "1970-01-20T16:13:20.000Z"

The second line is the classic bug: seconds passed where JavaScript wants milliseconds. The date lands 19 days after the epoch, which looks plausible enough to survive a code review.

Count the digits

Today a timestamp in seconds has 10 digits, milliseconds has 13, microseconds 16 and nanoseconds 19. That is enough to guess the unit when you cannot ask where the number came from. The converter on Toolsy Hub uses this rule on the whole part of the number:

  • up to 11 digits: seconds (this holds until the year 5138)
  • 12 to 14 digits: milliseconds
  • 15 to 17 digits: microseconds
  • 18 or more: nanoseconds

The cut points sit between the common lengths, so a 12 or 14 digit value still gets a sensible unit. It is a guess, so the tool also lets you pick the unit by hand.

Why nanoseconds need BigInt

A nanosecond timestamp for today is around 1.7 x 10^18. JavaScript numbers are 64-bit floats and only hold whole numbers exactly up to 9,007,199,254,740,991. Past that, digits get rounded:

Number(1700000000123456789n)   // 1700000000123456800
1700000000123456789n.toString() // "1700000000123456789"

So the converter keeps every input as whole nanoseconds in a BigInt and only turns it into a Date at the last step, after dividing down to milliseconds. Microsecond and nanosecond input comes out exact.

Negative timestamps round the other way

Dates before 1970 are negative. Truncating division gets them wrong by a second:

Math.trunc(-1500 / 1000) // -1  (rounds toward zero)
Math.floor(-1500 / 1000) // -2  (rounds toward the past)

-1500 ms is 1.5 seconds before the epoch, which falls inside the second that starts at -2. BigInt division truncates (-1500n / 1000n is -1n), so the converter has its own floor division that steps down by one when the remainder is not zero and the value is negative.

The range limit

A JavaScript Date stops at 8,640,000,000,000,000 ms either side of 1970. One millisecond past that is an invalid date:

new Date(8.64e15).toISOString()  // "+275760-09-13T00:00:00.000Z"
new Date(8.64e15 + 1).getTime()  // NaN

A converter should say "out of range" and not print "Invalid Date". The one on Toolsy Hub does, and it also rejects text that is not a number with its own message.

If you want to check a value without writing code, the converter is at https://www.toolsy-hub.com/tools/unix-timestamp-converter. It runs in the browser tab, shows seconds, milliseconds, microseconds, nanoseconds, ISO 8601 and UTC for any input, and converts a pasted list one value per line.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.