Unix Timestamp Converter: Epoch and Zones
Convert Unix timestamps safely: detect seconds versus milliseconds, render RFC 3339 with the right offset, handle DST gaps, leap seconds, and the 2038 limit.
Control Plane Labs Staff
Published October 3, 2026
The timestamp converter answers the question an incident review always asks: when did this actually happen? A Unix value is an absolute instant, so two people reading the same number will agree. The disagreement starts when one of them renders it in local time, guesses the wrong unit, or pastes a value that was never UTC to begin with.
What does a Unix timestamp actually count?
POSIX defines the value in Section 4.19, “Seconds Since the Epoch”, as a number that approximates the seconds elapsed since the Epoch. The key sentence is that “each and every day shall be accounted for by exactly 86400 seconds.” Unix time therefore has no slot for a leap second. The same section leaves the relationship between a system’s clock and true UTC “unspecified”, which is why clock discipline (NTP, smearing, or stepping) is an operations choice rather than part of the format.
Most ecosystems inherit that rule. JWT’s NumericDate
is seconds since the epoch “ignoring leap seconds,” and it may be non-integer. The
exp, nbf, and iat claims must use it, which is why the JWT decoder
shows them as plain numbers. ECMAScript’s time value
uses the same epoch at millisecond precision, does not account for leap seconds, and
covers exactly 100,000,000 days either side of 1970.
Seconds, milliseconds, or nanoseconds?
Unit confusion is the most common timestamp bug. A 13-digit value read as seconds lands tens of thousands of years in the future, and a 10-digit value read as milliseconds lands in January 1970. Digit count is a reliable first guess for dates near the present:
| Unit | Digits today | The instant 2026-10-03T12:00:00Z | Where you meet it |
|---|---|---|---|
| Seconds | 10 | 1791028800 |
date +%s, JWT claims, Prometheus API output |
| Milliseconds | 13 | 1791028800000 |
JavaScript Date.now(), Prometheus TSDB block times |
| Microseconds | 16 | 1791028800000000 |
Python datetime and timedelta resolution |
| Nanoseconds | 19 | 1791028800000000000 |
Go UnixNano(), time.Time internals |
The 10-digit window is wide but finite: it runs from 1000000000 (2001-09-09T01:46:40Z)
to 9999999999 (2286-11-20T17:46:39Z). Outside that window, choose the unit explicitly.
Real APIs mix them. The Prometheus HTTP API
accepts RFC 3339 or Unix seconds with optional decimals, always returns seconds, and
reports TSDB block bounds in milliseconds on the same page.
Language runtimes also bound the range. Go’s time package
documents that UnixNano() is undefined before 1678 or after 2262, because nanoseconds
since 1970 overflow an int64 there. UnixMilli() stays valid for roughly 292 million
years in each direction.
Which text format should you emit?
For logs, APIs, and tickets, emit RFC 3339:
full date, full time, and a mandatory offset (Z or ±hh:mm). The same instant renders
differently by zone but stays one instant:
2026-10-03T12:00:00Z UTC
2026-10-03T08:00:00-04:00 America/New_York (EDT)
2026-10-03T13:00:00+01:00 Europe/London (BST)
2026-10-03T17:30:00+05:30 Asia/Kolkata
An offset does not name a zone. When the zone matters, for example for a recurring
meeting or a maintenance window that must follow DST, use
RFC 9557, which adds a bracketed suffix
such as 2026-10-03T08:00:00-04:00[America/New_York]. The zone rules themselves come from
the IANA Time Zone Database, so keep runtimes and base
images current when governments change their rules.
HTTP is the exception. Headers such as Date, Last-Modified, and Expires use the
IMF-fixdate form defined in RFC 9110, Section 5.6.7,
for example Sat, 03 Oct 2026 12:00:00 GMT. Recipients must also accept two obsolete
forms. The HTTP header inspector guide covers how those dates
drive caching.
Where do conversions go wrong?
Local time at the boundary. Python’s datetime.fromtimestamp()
returns local time unless you pass tz. Go’s time.Unix() also returns a local Time,
though its Unix() result does not depend on location. Pass UTC explicitly in both:
from datetime import datetime, timezone
datetime.fromtimestamp(1791028800, tz=timezone.utc).isoformat()
# '2026-10-03T12:00:00+00:00'
Ambiguous local times. When US daylight time ends on November 1, 2026, Detroit sees
01:30 twice. 1793511000 renders as 2026-11-01T01:30:00-04:00 and 1793514600 as
2026-11-01T01:30:00-05:00. A log that drops the offset makes those two events
indistinguishable, and a scheduler that stores local wall time can run a job twice.
Check cron expressions against this with the cron expression tool.
Leap seconds. RFC 9110’s grammar allows 23:59:60, but Go cannot parse
a second-60 timestamp and Python’s datetime “does not support leap seconds.” The
IERS Bulletin C records UTC-TAI at
-37 s since 2017. Under CGPM Resolution 4 (2022),
the maximum UT1-UTC difference will be increased by 2035, so that UTC stays continuous for at least a century.
Until then, test what your parsers do with :60.
The 2038 limit. A signed 32-bit seconds counter tops out at 2147483647, which is
2038-01-19T03:14:07Z. glibc’s Y2038 design
makes 64-bit time opt-in on 32-bit platforms through _TIME_BITS=64. On 64-bit systems,
only 64-bit time is supported. Embedded agents, old database columns, and binary file
formats are where 32-bit values still hide.
A five-minute timestamp review
- Paste the raw value into the timestamp converter and confirm the detected unit against the source’s documentation, not the digit count alone.
- Record the UTC RFC 3339 form in the ticket, then add the local rendering with its offset.
- For anything scheduled, write the IANA zone name alongside the offset.
- Check for 32-bit storage if the value could pass 2038 within the data’s retention period.
- When an event looks an hour off, check for a DST transition before you blame clock drift.
Frequently asked questions
How do I tell seconds from milliseconds in a Unix timestamp?+
Does a Unix timestamp include leap seconds?+
Is a Unix timestamp in UTC?+
What is the difference between RFC 3339 and ISO 8601?+
What happens to 32-bit timestamps in 2038?+
Read next
- Try the timestamp converter.
- Decode
expandiatclaims with the JWT decoder. - Check a schedule in the cron expression tool.
- Read cron syntax explained for scheduler time-zone behavior.
Tags: #timestamps, #unix-time, #rfc3339, #timezones, #web-development