Unix Timestamps: Seconds, Milliseconds, and the Bugs They Cause

A timestamp like 1700000000 is unambiguous — until you forget whether it is seconds or milliseconds, or assume it means local time. This guide explains what a Unix timestamp really counts, why three-digit and thirteen-digit values behave differently, and the timezone and DST traps that break date math.

The Unix timestamp is one of the most quoted numbers in computing and one of the most misread. It is just a count of seconds, but the assumptions people attach to it — is it seconds or milliseconds? UTC or local? Does it include leap seconds? — are the source of an enormous number of off-by-a-thousand and off-by-a-timezone bugs.

What it actually counts

A Unix timestamp is the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970 — the Unix epoch. It is a single integer that names an exact instant in time, globally and unambiguously, because it is tied to UTC and not to any local calendar. 1,700,000,000 is the same moment whether you are in Tokyo or Toronto; only the human-readable rendering differs.

The standard definition ignores leap seconds: it counts "SI seconds" as if every day were exactly 86,400 seconds. That means a timestamp is not a pure count of physical seconds since the epoch, but it is monotonic and consistent across systems, which is what matters for software.

Seconds vs milliseconds vs microseconds

Different ecosystems pick different units, and mixing them up is the most common timestamp bug. You can tell them apart by digit count for any date after roughly 2001:

  • 10 digits (e.g. 1700000000) — seconds. Unix, PHP time(), most APIs, the "epoch" field in logs.
  • 13 digits (e.g. 1700000000000) — milliseconds. JavaScript Date.now(), Java System.currentTimeMillis(), most databases.
  • 16 digits — microseconds. Go time, some logging pipelines.
  • 19 digits — nanoseconds. High-resolution timers, tracing systems.

Because this confusion is so common, our timestamp converter auto-detects the unit from the digit count — paste a 10, 13, 16 or 19-digit number and it figures out which you meant and shows all four interpretations side by side.

The timezone trap: the instant vs the wall clock

A timestamp is an instant. A date-and-time string is an instant plus a timezone. The bug is treating one as the other. The same timestamp 1700000000 renders as:

UTC        2023-11-14 22:13:20
New York   2023-11-14 17:13:20 EST
Tokyo      2023-11-15 07:13:20 JST
London     2023-11-14 22:13:20 GMT

Notice Tokyo crosses into the next day. If you store "2023-11-14" as a user's birthday but you created that string by formatting a timestamp in a non-UTC zone, a user near a timezone boundary can have their birthday recorded on the wrong day. The fix is to store dates without a time component as plain calendar strings (or UTC), never as a midnight-local timestamp.

The related bug is parsing. new Date("2023-11-14") is treated as UTC midnight, but new Date("2023-11-14 00:00") is treated as local midnight — a one-character difference in the string changes the timezone assumption, and the resulting timestamp can be off by hours.

Daylight saving time breaks arithmetic

Timestamps themselves are immune to DST — they count seconds and do not care about clocks springing forward. But any math you do in local time is not. "Add 24 hours" and "add one day" are different operations in a timezone that has a 23-hour or 25-hour day. If you schedule a job for 2:30 AM local and that time does not exist on the spring-forward day, naive code either skips it or fires an hour early.

The 2038 problem, briefly

On 19 January 2038 at 03:14:07 UTC, a signed 32-bit integer runs out of room to count seconds and overflows to negative. Systems that store timestamps as a 32-bit int break at that instant. Modern platforms have moved to 64-bit time, where the range is effectively permanent (the year 292 billion). It is mostly a legacy-embedded and old-filesystem concern now, but it is a good reminder that the integer width of a timestamp is a real design decision.

A practical checklist

  1. Know your unit: 10 digits is seconds, 13 is milliseconds. Never assume.
  2. Store and transmit in UTC. Convert to local only for display.
  3. Calendar dates (birthdays, deadlines) should not be timestamps — store them as dates.
  4. Use ISO 8601 (2023-11-14T22:13:20Z, with the trailing Z) for readable, unambiguous strings.
  5. When in doubt, convert a value through a tool and check it against a date you already know.

If you have a timestamp on your screen and just need to know what moment it is — in UTC, your local time, and ISO 8601 at once — the converter does it instantly, entirely in your browser, with no server round-trip.

Timestamp ConverterUnix ⇄ date/time — open the tool