What epoch time is, and why developers keep tripping over it
A Unix timestamp — also called epoch time or POSIX time — is a single number: the seconds that have passed since 00:00:00 UTC on 1 January 1970, the moment known as the Unix epoch. That date was chosen in the early 1970s because it was a convenient round starting point for the first Unix systems, and it stuck. Today the same number turns up everywhere time is stored or sent between systems: API responses, JSON Web Tokens, database rows, log lines, file metadata and cache expiry headers. It is popular because it is unambiguous — a plain integer needs no date format, no month names and no timezone parsing — and because comparing two moments is just comparing two numbers.
The catch is that the number on its own tells you nothing about the unit. A timestamp is only meaningful once you know whether it counts seconds, milliseconds, microseconds or nanoseconds, and different ecosystems made different choices. That one missing fact is behind most timestamp bugs in the wild.
The seconds-vs-milliseconds pitfall: the most common timestamp bug
JavaScript's Date.now() returns milliseconds — 13 digits, currently starting 17… — while PHP's time(), Python's time.time(), Go's time.Now().Unix() and most databases return seconds — 10 digits. Mix them up and the result is wrong by a factor of 1,000, which is so large that the symptom is unmistakable once you know it. Feed a 13-digit millisecond value to code expecting seconds and you get a date thousands of years in the future. Feed a 10-digit second value to code expecting milliseconds and you land in January 1970, because 1,700,000,000 milliseconds is only about 20 days after the epoch — so a user born in 2023 suddenly has a birthday in 1970. The fastest diagnosis is the digit count: 10 digits is seconds, 13 is milliseconds, 16 is microseconds, 19 is nanoseconds. This converter counts the digits for you on Auto-detect, and the unit selector lets you override it when a value is ambiguous — short values such as 123456789 could be seconds in 1973 or milliseconds in 1970, and only the source system can settle that.
Worked examples
| Timestamp | Unit | What it is (UTC) |
|---|---|---|
0 | seconds | 1 January 1970, 00:00:00 — the epoch itself. Every timestamp is measured from here. |
1700000000 | seconds | 14 November 2023, 22:13:20. The same moment as 1700000000000 ms. |
1735689600 | seconds | 1 January 2025, 00:00:00 — a clean round date, handy for testing year boundaries. |
2147483647 | seconds | 19 January 2038, 03:14:07 — the largest value a signed 32-bit integer can hold (see below). |
−1 | seconds | 31 December 1969, 23:59:59 — one second before the epoch. Negative timestamps count backwards. |
Three more mistakes this converter catches
Treating a timestamp as if it had a timezone
A timestamp has no timezone: 1700000000 is one absolute moment, and it is 22:13 in London but 17:13 in New York on the same day. The timezone only appears when you display it. If two systems disagree about a time, check the display timezone first — the stored value is usually fine.
Losing precision on nanoseconds
A 19-digit nanosecond value is bigger than JavaScript's safe integer range, so ordinary Number arithmetic silently rounds it. This tool does its unit math with BigInt, so the seconds, milliseconds, microseconds and nanoseconds it shows are exact — the displayed date is still only precise to the millisecond, because that is all a calendar date can show.
Forgetting dates before 1970
Timestamps can be negative. Birth dates, historical records and anything before 1 January 1970 needs a minus sign — −315619200 is 1 January 1960. Code that rejects negative numbers, or stores timestamps in an unsigned type, corrupts every pre-1970 date it touches.
Assuming every day is 86,400 seconds
Unix time pretends every day is exactly 86,400 seconds and ignores leap seconds — the 27 extra seconds added since 1972 to keep atomic clocks aligned with the Earth's rotation. So a timestamp is about 27 seconds ahead of true solar time, and adding 86,400 to a timestamp does not always land on the same wall-clock time across a daylight-saving change.
Converting in code
If you would rather do it yourself than paste values here, the conversions are one line in most languages — the only thing to get right is the factor of 1,000:
// JavaScript — seconds to date, and back
const date = new Date(1700000000 * 1000); // ms for the Date constructor
const seconds = Math.floor(Date.now() / 1000); // Date.now() is milliseconds
# Python — timestamp to UTC date, and back
from datetime import datetime, timezone
dt = datetime.fromtimestamp(1700000000, tz=timezone.utc)
seconds = int(dt.timestamp())
The equivalent one-liners are date -u -d @1700000000 on Linux (date -u -r 1700000000 on macOS), SELECT FROM_UNIXTIME(1700000000) in MySQL and SELECT to_timestamp(1700000000) in PostgreSQL.
Leap seconds and the Year 2038 problem
Unix time ignores leap seconds by design, which keeps the arithmetic simple but means timestamps drift from astronomical time — about 27 seconds so far. For almost all software that drift is irrelevant; only astronomy and satellite systems need to care. The Year 2038 problem matters more: systems that store timestamps as a signed 32-bit integer max out at 2,147,483,647, which is 19 January 2038 at 03:14:07 UTC, and one second later the counter wraps to a large negative number — the system believes it is December 1901. Modern 64-bit systems store time in 64 bits and will not hit their limit for billions of years, but old embedded devices, legacy databases and 32-bit software still carry the risk. Try 2147483647 in the converter above to see the exact moment.