Understanding Unix Timestamp and Epoch Time
Understand Unix Epoch, time units, UTC, integer precision, the 2038 and 2106 limits, and leap seconds with practical code examples.
A timestamp locates an event on a time scale. Before exchanging a number, agree on its epoch, unit and clock semantics. A sensor counter since boot and Unix seconds may look similar while describing different things. Use the Unix Timestamp / Epoch Converter to inspect a value and the selected time zone without sending it to a server.
The Unix Epoch and the choice of 1970
Unix time uses 1970-01-01 00:00:00 UTC as its origin. This is a historical computing convention inherited from Unix, not a physical beginning of time. A different epoch would change the stored number, not the event. Do not confuse Unix time with NTP's 1900 epoch, GPS time or a vendor's counter since 2000.
How the counter works
For ordinary POSIX calendar arithmetic, advance the count by 86,400 for each nominal UTC calendar day. Thus 1970-01-02 00:00:00 UTC is 86400 seconds. Local days can have other lengths when civil clocks change. Positive values follow the epoch; −1 is the final second of 1969. A Unix timestamp has no time zone attached to its numeric value.
Seconds, milliseconds, microseconds and nanoseconds
| Timestamp unit | 1 s | 1700000000 s |
|---|---|---|
| Seconds (s) | 1 | 1700000000 |
| Milliseconds (ms) | 1000 | 1700000000000 |
| Microseconds (µs) | 1000000 | 1700000000000000 |
| Nanoseconds (ns) | 1000000000 | 1700000000000000000 |
Multiply seconds by 1000 for milliseconds and by 1,000,000,000 for nanoseconds. These operations change units, not accuracy. A clock resolved only to milliseconds does not gain nanosecond accuracy when six zeroes are appended. JavaScript Date expects milliseconds, whereas many C APIs and protocols use seconds. Always put the unit in the field name or schema.
UTC, offsets and IANA time zones
The same instant can be written as 2023-11-14 22:13:20 UTC or 23:13:20 in Europe/Paris. An offset such as +01:00 gives one displacement from UTC; an IANA identifier carries historical and future civil-time rules. A time zone abbreviation such as CST is ambiguous across regions.
Missing and repeated local times
In Paris, 2024-03-31 02:30 does not exist. On 2024-10-27, 02:30 occurs twice, at 00:30 UTC and 01:30 UTC. This converter rejects gaps and lets you select the earlier or later occurrence of a fold. It computes the calendar day of year from the selected zone's calendar fields, not elapsed multiples of 24 hours. Historical and future results depend on the browser's IANA data; political rules can change.
Worked conversion and representative values
Starting with 1700000000 seconds, multiplying by 1000 gives 1700000000000 milliseconds. Both identify 2023-11-14T22:13:20Z. Adding 123456789 nanoseconds gives 1700000000123456789 ns and an exact fractional second of .123456789. Showing this through Date alone displays .123, discarding 456789 ns from the calendar rendering.
| Unix seconds | ISO 8601 (UTC) |
|---|---|
| -1 | 1969-12-31T23:59:59Z |
| 0 | 1970-01-01T00:00:00Z |
| 1000000000 | 2001-09-09T01:46:40Z |
| 1700000000 | 2023-11-14T22:13:20Z |
| 2147483647 | 2038-01-19T03:14:07Z |
| 4294967295 | 2106-02-07T06:28:15Z |
For −1 ns, the exact instant is 1969-12-31T23:59:59.999999999Z. Its containing millisecond is −1 ms. Truncating integer division toward zero would incorrectly display the epoch. Use floor division when splitting negative timestamps and retain the remainder separately.
Signed 32-bit counters and the year 2038
A signed 32-bit seconds counter ranges from −2³¹ through 2³¹−1. Its final positive value, 2147483647, is 2038-01-19T03:14:07Z. The next second cannot fit. In C, signed overflow is undefined behavior; do not rely on an apparent wrap to 1901. Widen the operand before arithmetic, and check every on-disk and on-wire field as well as the processor's word size.
Unsigned 32-bit counters and 2106
An unsigned 32-bit counter holds 0 through 4294967295 seconds and reaches 2106-02-07T06:28:15Z. It cannot directly encode pre-1970 dates. Switching from signed to unsigned merely moves the endpoint and changes negative-value semantics; it is not a general migration to a long-lived timestamp format.
64-bit range, precision and JavaScript numbers
Integer width determines range at a chosen unit. Signed 64-bit seconds span about 292 billion years in either direction; signed 64-bit nanoseconds span only about 292 years, reaching 2262 on the positive side. Neither promises that a calendar library accepts that range. Binary64 represents all integers only through 2⁵³−1, so current nanosecond timestamps need BigInt or decimal strings in JavaScript. A 32-bit floating-point value is not an exact 32-bit seconds counter.
Leap seconds and POSIX limits
POSIX time is not a running count of every SI second since 1970. It does not assign a unique ordinary timestamp to the inserted UTC second labelled :60. Systems may step, repeat or smear time around an insertion according to their policy. Do not convert Unix to TAI or GPS by a timeless fixed offset, and do not use wall-clock subtraction for a guaranteed physical duration across a leap adjustment.
JavaScript / TypeScript: preserve the integer
const timestampNs = BigInt("1700000000123456789");
const divisor = BigInt(1_000_000);
const q = timestampNs / divisor;
const ms = timestampNs < 0 && timestampNs % divisor !== BigInt(0)
? q - BigInt(1) : q;
if (ms < BigInt("-8640000000000000") || ms > BigInt("8640000000000000")) {
throw new RangeError("Date");
}
const iso = new Date(Number(ms)).toISOString();
console.log(iso);
console.log(timestampNs.toString());
The result is 2023-11-14T22:13:20.123Z, while the original integer retains the full fraction. The converter checks the full nanosecond value against the Date endpoints before constructing a Date and reconstructs the exact ISO and RFC 3339 fraction separately. RFC 3339 uses four-digit years; expanded ISO years outside 0000–9999 are reported as unavailable in that row. RFC 2822 renders whole seconds and requires a year of at least 1900.
Python: avoid a floating-point round trip
from datetime import datetime, timezone, timedelta
epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
instant = datetime(2023, 11, 14, 22, 13, 20, 123456, tzinfo=timezone.utc)
delta = instant - epoch
timestamp_us = ((delta.days * 86400 + delta.seconds) * 1_000_000
+ delta.microseconds)
restored = epoch + timedelta(microseconds=timestamp_us)
assert restored == instant
print(timestamp_us, restored.isoformat())
Explicit UTC prevents the host's local zone from changing the result. timedelta arithmetic here preserves integer microseconds. A float returned by timestamp() can lose finer fractions; datetime itself does not store nanoseconds. For IANA conversion use zoneinfo, and choose a fold policy when interpreting local fields.
C and embedded storage
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
int main(void) {
int64_t seconds = INT64_C(1700000000);
int64_t milliseconds = seconds * INT64_C(1000);
int64_t after_2038 = (int64_t)INT32_MAX + INT64_C(1);
printf("%" PRId64 " %" PRId64 "\n", milliseconds, after_2038);
return 0;
}
These specific products fit int64_t. General conversion code must check bounds before multiplication. A 64-bit processor does not guarantee a 64-bit time_t, and serializing a raw time_t object creates ABI, byte-order and width dependencies. Specify an integer width, signedness, unit and epoch in the protocol. See Unix Timestamps in Embedded Systems, APIs and Databases for synchronization and storage design.
Frequent mistakes
- Passing seconds directly to Date, or inferring units solely from digit count.
- Converting a long decimal string to Number before BigInt; the lost digits cannot be recovered.
- Adding a time zone offset to a timestamp that already represents UTC.
- Accepting 31 February because a date constructor normalizes it into March.
- Treating a millisecond display as evidence of millisecond clock accuracy.
Technical FAQ
Does changing time zone change the timestamp?
No. It changes the calendar representation of the same instant. Interpreting a new set of local date fields is a separate operation that does require a zone.
Can a negative timestamp contain a fraction?
Yes. −0.5 s is half a second before the epoch. Preserve its sign through unit conversion and floor only the integer part needed by the calendar formatter.
Is the current timestamp a network time service?
No. The live clock reads your device clock. Its synchronization and accuracy depend on your operating system. It does not contact an NTP server.
Related tools and sources
Try Unix Timestamp / Epoch Converter, read Unix Timestamps in Embedded Systems, APIs and Databases, and estimate oscillator drift with the frequency tolerance guide and PPM ↔ Hz calculator.