Skip to content
100% in your browser. Nothing you paste is uploaded — all processing runs locally. Read more →

Unix timestamp seconds vs milliseconds — how to tell them apart

On this page
  1. What an epoch timestamp is
  2. 10 digits vs 13 digits (sec vs ms) — and when µs/ns show up
  3. Off-by-1000 bugs that break production
  4. How this converter auto-detects
  5. DST and timezone display caveats
  6. Tools

A Unix timestamp is one integer. The same instant can be 10 digits or 13 — seconds or milliseconds — and most languages accept either without complaining. Pass the wrong one to new Date() and you get January 1970, not a parse error.

This page is how to tell the units apart, why the mismatch keeps breaking production, and how to convert epoch to a date without guessing. Paste a number into the converter to see every format at once. It runs in your browser. Nothing is uploaded. There is no account.

What an epoch timestamp is

Unix time (also “epoch time”) counts from one fixed instant: 1970-01-01 00:00:00 UTC. The integer is timezone-independent. Two machines that agree on the number agree on the instant. Local clocks and daylight saving only appear when you format that integer for a human.

The original unit is seconds. 0 is the epoch. 1735689600 is 2025-01-01 00:00:00 UTC. Subtract two timestamps and you get a duration in the same unit. That is why logs, databases, JWT exp / iat / nbf, and most REST APIs still speak seconds.

For a longer primer, see What is Unix epoch?. To watch the current value tick, open the live now-clock. The number is not a calendar — it does not know months, timezones, DST, or leap seconds. Those are display problems, not part of the integer.

10 digits vs 13 digits (sec vs ms) — and when µs/ns show up

For any date in a working lifetime, digit count is a reliable tell:

Unit            Example (2025-01-01 00:00:00 UTC)    Typical digits
Seconds         1735689600                           10
Milliseconds    1735689600000                        13
Microseconds    1735689600000000                     16
Nanoseconds     1735689600000000000                  19

10 digits → seconds. C time_t, Python time.time(), Go Unix(), PostgreSQL EXTRACT(EPOCH ...), MySQL UNIX_TIMESTAMP(), most APIs.

13 digits → milliseconds. JavaScript Date.now(), new Date(ms), Java System.currentTimeMillis(), many metrics and real-time systems.

16 digits → microseconds. Postgres clock_timestamp(), Go UnixMicro(), some time-series stores.

19 digits → nanoseconds. Go UnixNano(), modern Linux st_mtim.tv_nsec, some tracing systems.

Negative numbers are valid — instants before 1970. Count the digits of the absolute value the same way. A fractional value like 1735689600.123 is still seconds; the fraction is the sub-second part.

The digit heuristic holds until year ~5138. An 11- or 12-digit number is usually a bug — convert it both ways before you trust it.

Off-by-1000 bugs that break production

The mismatch does not throw. It produces a date that looks like a date.

// API returned Unix seconds. JavaScript Date expects milliseconds.
const ts = 1735689600;
const date = new Date(ts);
date.toISOString();
// → "1970-01-21T02:08:09.600Z"   ← 21 days after the epoch, not 2025

A 10-digit second value, treated as milliseconds, lands in January 1970. A 13-digit millisecond value, treated as seconds, lands around year 50,000. Reviewers miss both because there is no exception.

What that looks like in production:

The fix is mechanical. Name the unit, then scale once:

function dateFromUnixSeconds(s) {
  return new Date(s * 1000);
}
function dateFromUnixMs(ms) {
  return new Date(ms);
}

If you are designing an API, put the unit in the field name (created_at_seconds, created_at_ms) and do not mix units in the same payload. If you are reading an unknown number, count the digits before you pass it to a constructor.

How this converter auto-detects

The Unix timestamp converter does not ask you to pick seconds or milliseconds. It looks at magnitude, then shows every common representation at once.

|n| < 10^11   →  seconds         (covers through year ~5138)
|n| < 10^14   →  milliseconds
|n| < 10^17   →  microseconds    (scaled down to ms)
|n| ≥ 10^17   →  nanoseconds     (scaled down to ms)

Paste 1735689600 and it reports Unix seconds. Paste 1735689600000 and it reports Unix milliseconds. Sixteen- and nineteen-digit values are treated as µs and ns and converted down so the date is still right.

You also get ISO 8601 UTC, local time, RFC 2822, day of week, and a new Date(...) constructor you can copy. Conversion runs in the page — Date.now() and new Date(...). Open DevTools → Network if you want to confirm nothing is uploaded. No signup.

Convert a timestamp →

DST and timezone display caveats

The integer is UTC. Daylight saving does not change it. When US clocks “spring forward,” Unix time keeps counting one second per second. Only the local display jumps.

That is why this converter always shows two clocks:

A few display traps that are not unit bugs:

If local time looks “off by an hour,” check the offset pill before you assume a seconds-vs-milliseconds mix-up. Off-by-1000 is a 1970-or-year-50000 error. Off-by-one-hour is almost always display.

Related on this host: What is Unix epoch?, the live now-clock, and the Year 2038 problem.

Tools