What is a Unix Timestamp?
A Unix timestamp is the number of seconds (or milliseconds) elapsed since 1970-01-01 00:00:00 UTC (the epoch). It is an absolute instant independent of time zone — the same moment yields the same timestamp number whether you are in Beijing, London, or New York.
Representing time as a single integer lets you store, compare, and subtract moments like ordinary numbers, free from the complexity of human calendars.
Seconds vs Milliseconds
The most common bug in practice is mixing units:
| Form | Digits | Example (same instant) | Common source |
|---|---|---|---|
| Seconds | 10 digits | 1700000000 |
Linux date +%s, MySQL UNIX_TIMESTAMP(), most backend APIs |
| Milliseconds | 13 digits | 1700000000000 |
JavaScript Date.now(), Java System.currentTimeMillis() |
Rule of thumb: 13-digit value ÷ 1000 ≈ 10-digit value. If the frontend passes a 13-digit value that the backend stores as seconds, the time jumps tens of thousands of years into the future. A good converter should auto-detect seconds vs milliseconds by digit count.
Time Zones and Local Display
The timestamp is an absolute UTC instant. When you see 2023-11-15 06:13:20 on a page, that is the UTC instant rendered in your local time zone:
const ts = 1700000000 // seconds
const d = new Date(ts * 1000) // note ×1000 to milliseconds
console.log(d.toString()) // local: Wed Nov 15 2023 06:13:20 GMT+0800
console.log(d.toISOString()) // UTC: 2023-11-14T22:13:20.000Z
Always store and transmit in UTC; format for the user's time zone only at display time. This is the only rule that keeps cross-timezone systems sane.
Daylight Saving Time (DST) Pitfalls
In regions with DST, two days a year have a "nonexistent hour" or a "repeated hour". Calendar-based arithmetic (e.g. "add 24 hours") drifts by one hour on DST transition days. The correct approach: do arithmetic on the timestamp (UTC integer), then format — never add/subtract on local wall-clock time.
Leap Seconds
Unix time increments at a fixed 86400 seconds per day and deliberately ignores leap seconds. The OS/NTP smooths leap seconds at a lower layer, transparent to almost all applications. Only extreme-precision domains (financial matching, satellite timing) need special handling.
Correct Conversion Across Languages
JavaScript (milliseconds → readable, watch the unit):
const sec = 1700000000
const d = new Date(sec * 1000) // seconds → milliseconds
const iso = d.toISOString() // UTC string
const local = d.toLocaleString('en-US') // local-time string
Python:
from datetime import datetime, timezone
ts = 1700000000
print(datetime.fromtimestamp(ts, tz=timezone.utc)) # be explicit about UTC
Go:
import "time"
t := time.Unix(1700000000, 0) // seconds; use time.UnixMilli for milliseconds
Best Practices
- Store in UTC: Use
TIMESTAMP(UTC) or an integer timestamp — never a "local time" column. - Transmit timestamps or ISO 8601: Avoid tz-less strings like
2023-11-15 06:13:20. - Format at display time per user tz: Use
Intl.DateTimeFormat, not hand-built strings. - Agree on units explicitly: Document seconds vs milliseconds; let the converter auto-detect as a fallback.
- Never do math on wall-clock time: Differences and schedules belong on the integer timestamp.