The short answer
Unix timestamp 0 is exactly 1970-01-01 00:00:00 UTC. That instant is called the Unix epoch. Everything else is counted from there.
| Unix timestamp | UTC date | What it means |
|---|---|---|
-86400 |
1969-12-31 00:00:00 |
one day before the epoch |
-1 |
1969-12-31 23:59:59 |
one second before the epoch |
0 |
1970-01-01 00:00:00 |
the Unix epoch |
1 |
1970-01-01 00:00:01 |
one second after the epoch |
86400 |
1970-01-02 00:00:00 |
one day after the epoch |
1000000000 |
2001-09-09 01:46:40 |
the billion-second milestone |
2147483647 |
2038-01-19 03:14:07 |
the signed 32-bit limit |
The timestamp is not "a date in your timezone." It is one global instant. Your timezone only changes the formatted label printed on top of that instant.
Open the live epoch clock if you want to see the current value move once per second, or use the epoch-to-date converter to check any number from this article.
What "epoch" means in plain English
An epoch is a zero point. It is the date a system chooses as the start of its count.
Unix time chose 1970-01-01 00:00:00 UTC as that zero point. The timestamp then answers one simple question: how many seconds are we from that instant?
That gives you the mental model:
0means "at the zero point."10means "ten seconds after the zero point."-10means "ten seconds before the zero point."1700000000means "1,700,000,000 seconds after the zero point."
This is why the same number can be displayed as different clock times in different places. 0 is midnight UTC, but in New York it displays as the evening of December 31, 1969. The instant did not change; only the local label changed.
Why January 1, 1970?
There is no hidden astronomical event on January 1, 1970. The practical answer is that Unix was being built at Bell Labs around 1969-1970, and the developers needed a clean, recent reference date for system time.
Dennis Ritchie's history of Unix describes the system as being born in 1969, moving through the PDP-7 and PDP-11 period in 1970-1971, and becoming the foundation for the later Unix interface. In that context, 1970-01-01 was close enough to the start of the project, easy to remember, and far enough back to cover normal file and process timestamps for the new system.
POSIX later made the convention formal. The Open Group's POSIX text defines the Epoch as zero hours, zero minutes, zero seconds on January 1, 1970 UTC, and defines seconds since the Epoch with each represented day accounted for as exactly 86,400 seconds.
The important point for modern developers is not the romance of the date. It is that almost every server runtime, database, browser, log system, queue, API, and analytics pipeline now shares the same reference instant.
Negative Unix timestamps
Negative timestamps are not special syntax. They are just signed numbers before the epoch.
| Timestamp | UTC date | Common use |
|---|---|---|
-1 |
1969-12-31 23:59:59 |
last second before Unix time starts |
-86400 |
1969-12-31 00:00:00 |
one day before the epoch |
-31536000 |
1969-01-01 00:00:00 |
one non-leap year before the epoch |
-2208988800 |
1900-01-01 00:00:00 |
NTP's epoch as a Unix timestamp |
-11644473600 |
1601-01-01 00:00:00 |
Windows FILETIME's epoch as a Unix timestamp |
Most modern language libraries can represent these values. JavaScript can format new Date(-86400000).toISOString() as 1969-12-31T00:00:00.000Z; Python can create datetime.fromtimestamp(-86400, tz=timezone.utc); Java can use Instant.ofEpochSecond(-86400).
The catch is at the edges:
- Some spreadsheets and business tools refuse dates before 1900.
- Some database functions accept negative epochs, but others clamp or return
NULL. - Some old code stores timestamps in unsigned integers, which cannot represent dates before 1970.
- Some historical dates are calendar-sensitive, especially before modern timezone rules were standardized.
If your data includes births, archives, certificates, legal records, old media files, or anything before 1970, store the timestamp in a signed 64-bit field and keep the unit in the column name, such as event_time_s or event_time_ms.
Seconds, milliseconds, microseconds, nanoseconds
Strict Unix/POSIX time is seconds since the epoch. Real systems often keep the same epoch but change the unit.
| Digits in 2026 | Likely unit | Example | Reads as UTC |
|---|---|---|---|
| 10 | seconds | 1700000000 |
2023-11-14 22:13:20 |
| 13 | milliseconds | 1700000000000 |
2023-11-14 22:13:20 |
| 16 | microseconds | 1700000000000000 |
2023-11-14 22:13:20 |
| 19 | nanoseconds | 1700000000000000000 |
2023-11-14 22:13:20 |
This is the timestamp bug that shows up in production logs all the time:
1700000000as seconds =2023-11-14 22:13:20 UTC1700000000as milliseconds =1970-01-20 16:13:20 UTC1700000000000as milliseconds =2023-11-14 22:13:20 UTC1700000000000as seconds = a far-future year that many libraries cannot handle cleanly
Name the field with the unit. created_at is ambiguous. created_at_s, created_at_ms, or created_at_unix_ms prevents the next person from guessing.
Timezone: where the confusion actually starts
A Unix timestamp does not store UTC, PST, EST, CET, or any other timezone label. It stores an instant. Formatting code chooses the label later.
Take timestamp 0:
- UTC:
1970-01-01 00:00:00 - America/New_York:
1969-12-31 19:00:00during standard time - Asia/Tokyo:
1970-01-01 09:00:00
All three are the same instant. They only look different because the display timezone changed.
The storage rule is simple: store instants as Unix timestamps or UTC datetimes. Apply the user's IANA timezone only when displaying or when turning a local wall-clock appointment into an instant.
The comparison rule is just as simple: compare instants, not formatted strings. 2026-03-08 02:30 in a local timezone may be nonexistent because of daylight saving time, but a Unix timestamp is still an unambiguous point on the timeline.
Storage limits and the Year 2038 problem
The Unix timestamp format is not the real limit. The storage type is.
| Storage type | Range | Practical consequence |
|---|---|---|
| signed 32-bit seconds | -2147483648 to 2147483647 |
1901-12-13 20:45:52 to 2038-01-19 03:14:07 |
| unsigned 32-bit seconds | 0 to 4294967295 |
1970-01-01 to 2106-02-07 06:28:15, but no pre-1970 dates |
| signed 64-bit seconds | about +/- 292 billion years | effectively enough for normal application timestamps |
JavaScript Date |
+/- 100,000,000 days from 1970 | wide range, but millisecond-based and subject to number precision rules |
The Year 2038 problem is the signed 32-bit overflow. After 2147483647, a signed 32-bit counter wraps into negative territory and can look like a date in 1901. Modern 64-bit operating systems and runtimes are mostly past this, but embedded devices, old C code, binary protocols, old database schemas, and file formats can still carry the risk.
Leap seconds: the awkward part
POSIX-style Unix time treats every represented day as exactly 86,400 seconds. UTC, the civil time scale, can include leap seconds to keep atomic time aligned with Earth's rotation.
That mismatch is why leap seconds feel strange in Unix systems. A civil clock may say 23:59:60, but POSIX time does not create a clean extra integer for that label. Different systems handle the event by stepping, repeating, smearing the time across a window, or relying on upstream time synchronization.
For ordinary logs, API timestamps, JWT expiry values, database rows, and UI dates, Unix time is still the right tool. For precision timing, distributed tracing, finance, satellites, or scientific measurement, do not assume Unix timestamps alone are a complete time scale. You may need monotonic clocks, TAI/GPS-aware time, or an explicit leap-second table.
One more detail worth getting right: the international decision was not a generic "2026 vote to abolish leap seconds." The 27th CGPM adopted Resolution 4 in 2022, deciding that the maximum allowed UT1-UTC difference should be increased in or before 2035 and asking for implementation planning toward the 2026 CGPM meeting.
Other epochs you will meet
Unix is the dominant epoch for web software, but not the only one. Other systems picked different zero points and different tick sizes.
| System | Epoch | Unit | Unix conversion shortcut |
|---|---|---|---|
| Unix / POSIX | 1970-01-01 00:00:00 UTC |
seconds | already Unix seconds |
| Unix milliseconds | 1970-01-01 00:00:00 UTC |
milliseconds | divide by 1000 |
| Windows FILETIME | 1601-01-01 00:00:00 UTC |
100 ns ticks | filetime / 10000000 - 11644473600 |
.NET DateTime.Ticks |
0001-01-01 00:00:00 |
100 ns ticks | (ticks - 621355968000000000) / 10000000 |
| NTP | 1900-01-01 00:00:00 UTC |
seconds | ntp_seconds - 2208988800 |
| Apple Core Data / CFAbsoluteTime | 2001-01-01 00:00:00 UTC |
seconds | core_data_seconds + 978307200 |
| GPS time | 1980-01-06 00:00:00 |
seconds, no UTC leap seconds | convert with the current GPS-UTC offset |
| Excel 1900 date system | 1899-12-30-style serial base |
days | handle the 1900 leap-year bug explicitly |
The pattern is always the same: identify the epoch, identify the unit, apply the offset, then format the resulting instant. The offset is easy; the mistakes come from assuming every large number is Unix milliseconds.
Microsoft's FILETIME documentation defines FILETIME as 100-nanosecond intervals since January 1, 1601 UTC. Microsoft's .NET documentation defines DateTime.Ticks as 100-nanosecond intervals since January 1, 0001 in the Gregorian calendar. Those are epoch systems too; they just are not Unix time.
A quick debugging checklist
When a timestamp looks wrong, do these checks before blaming the library:
- Count the digits: 10, 13, 16, or 19 usually tells you seconds, milliseconds, microseconds, or nanoseconds.
- Check the timezone used for display. UTC output and local output can show different calendar dates for the same instant.
- Check signedness. Unsigned storage cannot represent pre-1970 dates.
- Check the upper bound.
2147483647is the signed 32-bit 2038 edge. - Check the source system. FILETIME, .NET ticks, NTP, GPS, Excel, and Core Data all use different epochs.
- Check whether the value is an instant or a duration. A stopwatch duration should usually use a monotonic clock, not wall-clock Unix time.
If the value lands in January 1970, you probably treated seconds as milliseconds. If it lands thousands of years in the future, you probably treated milliseconds as seconds. If it shifts by one hour, look for timezone or daylight-saving conversion. If it shifts by years, look for the wrong epoch.
How this page fits the timestamp cluster
This article is the conceptual starting point: what the epoch is, why timestamp 0 matters, and what assumptions travel with the number.
For the next step, use the page that matches your task:
- Convert Unix number to a date: Unix time to date
- Convert a date to a Unix number: Date to epoch
- Choose the right converter: Epoch converter guide
- Get the current timestamp in code: Current Unix timestamp
- Fix unit mistakes: Milliseconds vs seconds
- Store timestamps safely: Timestamps in databases
- Avoid production bugs: Common timestamp bugs
If you remember only one thing, remember this: a Unix timestamp is one instant counted from 1970-01-01 00:00:00 UTC. The timezone, display format, and unit are separate decisions.
FAQ
- What is Unix timestamp zero?
- Unix timestamp 0 is 1970-01-01 00:00:00 UTC. It is the reference instant, or epoch, from which Unix time counts.
- Why does Unix time start in 1970?
- Unix was created at Bell Labs around 1969-1970, and 1970-01-01 became a convenient recent zero point for the system's time counter. POSIX later standardized that epoch as zero hours, zero minutes, zero seconds on January 1, 1970 UTC.
- Does a Unix timestamp include a timezone?
- No. The number represents one instant. Timezones only affect how that instant is displayed, such as UTC, America/New_York, Europe/London, or Asia/Tokyo.
- Can Unix timestamps be negative?
- Yes, on systems that support signed timestamp values. -1 is 1969-12-31 23:59:59 UTC, and -86400 is 1969-12-31 00:00:00 UTC.
- Is epoch time always seconds?
- POSIX Unix time is seconds since the epoch, but many APIs store the same epoch in milliseconds, microseconds, or nanoseconds. In 2026, modern Unix seconds are usually 10 digits, milliseconds 13 digits, microseconds 16 digits, and nanoseconds 19 digits.
- What is the maximum Unix timestamp?
- It depends on the storage type. A signed 32-bit Unix timestamp ends at 2147483647, which is 2038-01-19 03:14:07 UTC. A signed 64-bit seconds value is effectively unlimited for normal software dates.
- What is POSIX time vs Unix time?
- In everyday software work they mean the same timestamp. POSIX time is the standards-defined form: seconds since the Unix epoch, with every represented day treated as exactly 86400 seconds.
- Does Unix time count leap seconds?
- No. POSIX-style Unix time does not create a distinct timestamp for 23:59:60. Systems either step, repeat, smear, or otherwise handle leap seconds outside the simple timestamp number.
- Why do some timestamps show dates in 1970?
- A common reason is a unit mix-up: a seconds value was interpreted as milliseconds. For example, 1700000000 seconds is 2023-11-14 22:13:20 UTC, but 1700000000 milliseconds is 1970-01-20 16:13:20 UTC.
- Is Windows FILETIME the same as Unix time?
- No. Windows FILETIME counts 100-nanosecond intervals since 1601-01-01 UTC. To convert FILETIME to Unix seconds, divide by 10000000 and subtract 11644473600.