Unix Timestamps Explained: Seconds vs Milliseconds

The single most common timestamp bug is a factor of 1000. Here is how Unix time works and how to spot seconds-vs-milliseconds mistakes fast.

A Unix timestamp is a single number: the count of time units elapsed since midnight UTC on January 1, 1970 — the "Unix epoch." No timezone, no calendar, no formatting — just a count, which is exactly why it's so widely used for storage and comparison. The entire source of confusion is that different systems count in different units.

Seconds vs. milliseconds

Most systems — Unix/Linux itself, PHP, Python's time.time(), PostgreSQL, and most REST APIs — express Unix time in seconds. JavaScript is the notable exception: Date.now() and new Date().getTime() return milliseconds since the epoch.

This single difference is responsible for an enormous share of timestamp bugs. The tell is the number of digits: a current seconds-based timestamp is 10 digits (e.g. 1786752000); a current milliseconds-based timestamp is 13 digits (e.g. 1786752000000). If you feed a seconds value into something expecting milliseconds, you get a date near January 1970. If you feed a milliseconds value into something expecting seconds, you get a date thousands of years in the future.

How to spot it fast

Count the digits. As of 2026, current seconds-based timestamps are in the 1.78-billion range (10 digits); current milliseconds-based timestamps are in the 1.786-trillion range (13 digits). If a "current" timestamp you're debugging doesn't look like one of those two ranges, you're almost certainly looking at a unit mismatch, not a logic bug — check the conversion before you check the rest of your code.

Converting between them

Seconds to milliseconds: multiply by 1000. Milliseconds to seconds: divide by 1000 (and typically floor or round, since sub-second precision is usually irrelevant once you're back in seconds). In JavaScript specifically:

// Seconds -> JS Date
new Date(secondsValue * 1000)

// JS Date -> seconds
Math.floor(Date.now() / 1000)

The most common version of this bug in practice: taking a seconds-based timestamp straight from an API response and passing it directly to new Date() without multiplying by 1000 — JavaScript interprets it as milliseconds, and you get a date in 1970 instead of today.

Why use Unix time at all

Timestamps as plain numbers are easy to store, compare, and sort — timestampA > timestampB is a valid "which happened later" check with no timezone or string-parsing logic involved. They're also unambiguous across systems: a Unix timestamp means the same instant everywhere in the world, whereas a formatted date string like "03/04/2026" is ambiguous (March 4th or April 3rd?) without knowing the locale it was written in.

The tradeoff is that raw timestamps aren't human-readable, so they need converting to a calendar date for display, and that conversion is where a timezone has to be chosen — the timestamp itself is timezone-agnostic, but rendering it as "August 10, 2026, 3:00 PM" requires picking one.

Converting timestamps directly

Rather than debugging unit mismatches by hand, paste a timestamp into the Timestamp Converter to see it rendered as a readable date instantly, or go the other direction and convert a date into a Unix timestamp. It's the fastest way to sanity-check whether a value you're looking at is actually what you think it is before you build logic around it.

The short version

Unix time is a plain count of seconds since 1970 in almost every system except JavaScript, which counts milliseconds. When a timestamp looks wrong, count its digits before you debug anything else — 10 digits means seconds, 13 means milliseconds, and mixing the two up is responsible for most Unix timestamp bugs you'll ever see.