The Unix timestamp cheat sheet every developer wishes they had bookmarked
Seconds vs milliseconds vs microseconds, ISO 8601 vs RFC 3339, timezones, DST, leap seconds โ the reference for every 'wait, is this in ms?' moment.
Seconds, milliseconds, microseconds
Every timestamp bug starts with a unit mismatch. The three you'll actually see:
- Seconds โ Unix's original unit. 10 digits until year 2286. Used by
time()in C,time.time()in Python (as a float),Time.now.to_iin Ruby, and most cron systems. - Milliseconds โ JavaScript's
Date.now(), Java'sSystem.currentTimeMillis(), most APIs designed after 2005. 13 digits. - Microseconds / nanoseconds โ Go's
time.Now().UnixNano(), database timestamps like Postgrestimestamp. 16 or 19 digits.
The fast heuristic: count digits. 10 = seconds. 13 = milliseconds. 16+ = micro or nano.
The Y2K38 problem
Signed 32-bit integers overflow on January 19, 2038 at 03:14:07 UTC. Any system still using 32-bit time_t โ mostly embedded devices โ silently wraps to 1901. Every modern language and database uses 64-bit now, but check your embedded stack.
ISO 8601, RFC 3339, and JavaScript
ISO 8601 is a large family of date formats. RFC 3339 is a strict subset โ the one everyone actually means when they say "ISO date":
2026-08-11T14:30:00Z (UTC, Z suffix)
2026-08-11T14:30:00.123Z (with milliseconds)
2026-08-11T14:30:00+02:00 (with timezone offset)
JavaScript's Date.prototype.toISOString() always produces RFC 3339 in UTC. new Date(string) accepts most ISO variants but has one trap: date-only strings ("2026-08-11") parse as UTC, while datetime strings without a timezone ("2026-08-11T14:30") parse as local time. Off-by-one-day bugs come from this.
Timezones the sane way
Three rules:
- Store in UTC. Every timestamp in the database, the log, the message queue: UTC. No exceptions.
- Convert at the boundary. Only convert to a user's local time when rendering, and only using their real timezone (from browser
Intl.DateTimeFormat().resolvedOptions().timeZone, not their UTC offset โ offsets change with DST). - Never store an offset.
+05:30doesn't tell you which zone it came from. Store the IANA timezone name (Asia/Kolkata) if you need to reconstruct local time later.
DST is a formatting problem, not a math problem
Adding 24 hours to a timestamp doesn't always land you at the same clock time the next day โ DST transitions eat or add an hour. Add "1 day" only via a real date library (date-fns, luxon, Temporal) that understands calendar arithmetic. Adding 86400 seconds is a math operation and gives the wrong answer twice a year.
Leap seconds (mostly) don't exist for you
Unix time deliberately ignores leap seconds โ a Unix day is always 86,400 seconds. When a leap second is added, the system clock either slows down or repeats a second. Google's NTP servers "smear" it across the surrounding hours; most systems just have a duplicated second. Unless you're doing financial trading or scientific timing, ignore.
Also: the ITU voted in 2022 to abolish leap seconds by 2035. By the time you next hit a bug, they may be gone entirely.
The "wait, is this local?" checklist
When a timestamp looks wrong:
- Count the digits to check the unit.
- Look for a
Zor offset โ if neither, it's ambiguous and probably local. - Check what
toString()prints โ JavaScript's defaultDate.toString()renders in local time, which trips up anyone comparing it to a UTC log. - Compare to
Date.now()โ is it close to the current time? Off by exactly 3600? Off by exactly 5:30? That's your timezone hint.
Timestamp Converter shows all four representations at once โ Unix (s/ms), ISO 8601, local, UTC โ and a live-updating current timestamp for quick reference.
Common conversions you'll want handy
- JavaScript ms โ Python s:
ms / 1000(Python'stime.time()returns a float). - Postgres timestamp โ Unix s:
EXTRACT(EPOCH FROM ts). - Go time.Time โ Unix ms:
t.UnixMilli()(added in Go 1.17). - Excel serial date โ Unix s:
(serial - 25569) * 86400(25569 = days between 1900 and 1970).
Related tools:
- Cron Generator โ when the timestamp is a schedule you're trying to build.
- JSON Formatter โ when the timestamps are buried in a JSON payload.