July 15, 2026

Understanding Unix Timestamps: Why Computers Count Time in Seconds

A Unix timestamp is the number of seconds elapsed since midnight UTC on January 1, 1970 — a single integer that's faster to compare, sort, and do math on than a date string. Here's what that number means and the seconds-vs-milliseconds mixup that trips up almost everyone at some point.

Timestamp Converter showing a Unix timestamp converted to its equivalent human-readable date and time

The one idea: counting seconds from a fixed starting point

A Unix timestamp is simply the number of seconds that have elapsed since midnight UTC on January 1, 1970 — a moment programmers call "the epoch." No months, no leap years to think about, no timezone ambiguity baked into the number itself. Just one integer that keeps counting upward, forever.

That simplicity is exactly why it's everywhere: comparing two timestamps to see which came first is just comparing two numbers. Calculating a duration is just subtraction. No calendar logic required.

Seconds vs. milliseconds — the #1 source of confusion

Some systems (like Unix/Linux conventions and most databases) use seconds — a 10-digit number today. JavaScript's Date object, by contrast, uses milliseconds — a 13-digit number. Mixing the two up is one of the most common timestamp bugs: multiply or divide by 1000 in the wrong direction and you land on a date decades off from what you expected.

  • 10 digits (e.g. 1716239022) → seconds
  • 13 digits (e.g. 1716239022000) → milliseconds

The precise rule behind that digit count: any value below 10,000,000,000 is seconds, since ten billion seconds lands in the year 2286 — a normal, real-world date that large can only be milliseconds. Getting this backwards produces two distinctive failure modes: treating milliseconds as seconds collapses a real date down to a few weeks after the epoch in January 1970, while treating seconds as milliseconds rockets a normal date forward to the year 56970.

Why this matters for JWTs specifically

JWT tokens use Unix timestamps in seconds for their exp (expiration) and iat (issued at) claims. When you're debugging why a token expired earlier than expected, converting that raw number to an actual date is usually the fastest way to spot the bug — a token issued with the wrong exp value looks completely normal until you see what date it actually decodes to.

Why not just store a readable date string?

You could — but a plain integer is faster to compare, sort, and do math on than parsing a string every time, takes less storage, and sidesteps timezone-formatting bugs entirely until the moment you actually need to display it to a human. The timestamp is the source of truth; the readable format is just a presentation layer applied at the last possible step.

Want to try this yourself?

Open Timestamp Converter