Unix seconds vs milliseconds
On this page
TL;DR. When in doubt, use Unix seconds — the older, more portable unit. Use milliseconds when the API specifically demands them (JavaScript, Java) or when sub-second precision matters. Mismatched units cause the single most common time bug: dates that are off by a factor of 1000.
How big is each, in practice
For 2025-01-01 00:00:00 UTC:
Seconds: 1735689600 (10 digits)
Milliseconds: 1735689600000 (13 digits)
Microseconds: 1735689600000000 (16 digits)
Nanoseconds: 1735689600000000000 (19 digits)
The number-of-digits heuristic is reliable enough that the converter auto-detects format from magnitude alone.
Where each is the convention
Seconds
- C
time_t— the original, since 1970. - Python
time.time()— returns float seconds with sub-second precision. - Go
time.Now().Unix()— explicitly seconds. - PostgreSQL
EXTRACT(EPOCH FROM NOW())— seconds (with fractional component). - MySQL
UNIX_TIMESTAMP()— seconds. - HTTP cookie
Max-Age— seconds. - JWT
exp,iat,nbfclaims — seconds (per RFC 7519). - Most third-party REST APIs — seconds.
Milliseconds
- JavaScript
Date.now()— ms, always. The defining quirk. - Java
System.currentTimeMillis()— ms. - MongoDB ObjectId timestamp — embedded as seconds in the ID, but the API exposes ms.
- Many real-time / metrics systems — ms for finer ordering.
- Server-Sent Events
idfield — sometimes ms.
Microseconds
- PostgreSQL
clock_timestamp()— sub-millisecond precision. - Go
time.Time.UnixMicro()— for high-precision logging. - Time-series databases — InfluxDB, TimescaleDB default to ns or µs.
Nanoseconds
- Linux file
statsince ~2010 —st_mtim.tv_nsec. - Go
time.Time.UnixNano()— most precise standard. - Some distributed-tracing systems — for sub-µs resolution.
The 1000× bug
The single most common time bug in production code:
// Bug: API returned seconds; passed straight to JavaScript Date
const ts = await fetchTimestamp(); // 1735689600 (seconds, from API)
const date = new Date(ts);
console.log(date.toISOString());
// → "1970-01-21T02:08:09.600Z" ← Wrong! This is treated as ms.
The result looks vaguely correct (it’s a date, no parse error), so the bug often slips through code review. It manifests as:
- Cache TTLs that immediately expire (or never expire).
- “Updated 55 years ago” timestamps in the UI.
- Date filters that return everything (or nothing).
- Auth tokens that look valid but server rejects.
The fix:
const date = new Date(ts * 1000); // ts is seconds → multiply
// → "2025-01-01T00:00:00.000Z" ← Right.
Or use a clear-named helper:
function dateFromUnixSeconds(s: number): Date {
return new Date(s * 1000);
}
function dateFromUnixMs(ms: number): Date {
return new Date(ms);
}
Detection rules
If you don’t know whether a number is seconds or milliseconds, the magnitude tells you (for any reasonable date in your lifetime):
< 10^11 → seconds (covers up to year ~5138)
< 10^14 → milliseconds (covers up to year ~5138)
< 10^17 → microseconds
≥ 10^17 → nanoseconds
The converter uses exactly this heuristic.
API design
If you’re designing an API and need to choose:
- Use seconds for backward compatibility — most clients expect them.
- Use milliseconds when sub-second precision matters — e.g., ordering events in distributed systems.
- Document the unit explicitly in field names and docs:
created_at_seconds: 1735689600created_at_ms: 1735689600000
- Don’t mix units within a single API. Pick one and stick with it.
- For ISO 8601, both are equivalent — the timestamp encodes
microsecond precision:
2025-01-01T00:00:00.123456Z.
Common library defaults
When in doubt, check the docs — the defaults vary:
| Library | Default | Notes |
|---|---|---|
dayjs (JS) | ms | Wraps Date |
luxon (JS) | ms | Same |
moment (JS) | ms | Same |
date-fns (JS) | ms | Works on Date directly |
pendulum (Python) | seconds (float) | Wraps stdlib |
arrow (Python) | seconds | Same |
chrono (Rust) | seconds | Utc::now().timestamp() |
time crate (Rust) | seconds | OffsetDateTime::now_utc().unix_timestamp() |
| Go stdlib | seconds | Unix() returns int64 seconds |
| Joda-Time (Java) | ms | Wraps Instant |
Try the tools
- Live now-clock — see current time in seconds and milliseconds simultaneously
- Timestamp converter — paste any number, get every format
- What is Unix epoch? — fundamentals