Unix Timestamp: Seconds vs Milliseconds
Updated: May 2026
The single most common timestamp bug is mixing up seconds and milliseconds. Getting it wrong by a factor of 1000 shifts your date by 11.5 days if you treat seconds as milliseconds, or pushes it back to 1970 if you divide milliseconds as if they were seconds. This guide explains how to tell them apart and how to handle them safely.
Free · No upload · Instant
The quick rule: count the digits
| Digits | Unit | Example | Represents |
|---|---|---|---|
| 10 | Seconds | 1735689600 | 2025-01-01 00:00:00 UTC |
| 13 | Milliseconds | 1735689600000 | 2025-01-01 00:00:00 UTC |
| 16 | Microseconds | 1735689600000000 | 2025-01-01 00:00:00 UTC |
| 19 | Nanoseconds | 1735689600000000000 | 2025-01-01 00:00:00 UTC |
For dates between 2001 and 2286, this digit count is reliable. Negative timestamps (pre-1970) need an absolute value check. The heuristic breaks for extremely distant future dates, but those are irrelevant in practice.
Which languages use which unit?
| Language / system | Default unit | How to get seconds |
|---|---|---|
C / POSIX time() | Seconds | Direct |
Python time.time() | Seconds (float) | int(time.time()) |
PHP time() | Seconds | Direct |
Go time.Now().Unix() | Seconds | Direct |
SQL UNIX_TIMESTAMP() | Seconds | Direct |
JavaScript Date.now() | Milliseconds | Math.floor(Date.now()/1000) |
Java System.currentTimeMillis() | Milliseconds | System.currentTimeMillis()/1000 |
Kotlin System.currentTimeMillis() | Milliseconds | System.currentTimeMillis()/1000 |
Swift Date().timeIntervalSince1970 | Seconds (Double) | Int(Date().timeIntervalSince1970) |
Rust SystemTime::now() | Duration (custom) | .duration_since(UNIX_EPOCH)?.as_secs() |
Auto-detection pattern
When you receive a timestamp from an external source and don't know its unit, use a digit count or magnitude check:
// JavaScript
function normalizeToMs(ts) {
const n = Number(ts);
if (Math.abs(n) > 1e12) return n; // already milliseconds
return n * 1000; // convert seconds to ms
}
// Python
def normalize_to_seconds(ts):
ts = int(ts)
if abs(ts) > 10**12:
return ts // 1000 # milliseconds → seconds
if abs(ts) > 10**15:
return ts // 10**6 # microseconds → seconds
return ts # already seconds
// PHP
function toSeconds(int $ts): int {
if (abs($ts) > 1e12) return (int)($ts / 1000);
return $ts;
}
When building internal APIs or storing timestamps in databases, always document the unit in variable names: created_at_s for seconds or created_at_ms for milliseconds. This prevents ambiguity at the seams between systems.
What goes wrong when you mix them up
- Treating seconds as milliseconds:
new Date(1735689600)in JavaScript gives January 21, 1970 — 11.5 days after the epoch. The bug is subtle because the result is a valid date, just the wrong one. - Treating milliseconds as seconds:
datetime.fromtimestamp(1735689600000)in Python raises aValueError(year out of range) — at least this one is obvious. - Storing mixed units in one column: If some rows contain seconds and others milliseconds, sorting and filtering break silently.
- Arithmetic errors: Adding 86 400 to a millisecond timestamp adds only 86.4 seconds, not one day.
Converting between units
// Seconds → Milliseconds
const ms = seconds * 1000;
// Milliseconds → Seconds (integer)
const s = Math.floor(ms / 1000);
// Python
ms = s * 1000
s = ms // 1000
// PostgreSQL
SELECT (ts_ms / 1000)::bigint AS ts_seconds FROM events;