A Unix timestamp, also called epoch time or Unix time, is the number of seconds that have passed since 00:00:00 UTC on January 1, 1970, not counting leap seconds. For example, 1735689600 is exactly 2025-01-01 00:00:00 UTC, and that same number means the same instant everywhere on Earth.

Because it's a single integer with no time zone attached, Unix time is what sits underneath most created_at columns, JWT expiry claims and log lines. This guide covers the seconds-vs-milliseconds trap, how to convert timestamps in JavaScript, Python, SQL and Excel, how leap seconds are handled, negative timestamps, and the exact moment the Year 2038 problem hits. To convert a value right now, paste it into the Timestamp Converter.

What a Unix timestamp represents

The starting point, 1970-01-01 00:00:00 UTC, is called the Unix epoch. A timestamp is a count of seconds from that moment: 0 is the epoch itself, 86400 is one day later, and 1000000000 is 2001-09-09 01:46:40 UTC. The number carries no time zone. Time zones only enter when you turn the number into a calendar date and clock time for display, so 1735689600 shows as midnight on New Year's Day in London but as 7:00 p.m. on December 31 in New York, which is five hours behind UTC in winter. It's still one moment.

That's why the terms are used interchangeably. "Epoch time" emphasizes the starting point, "Unix time" the system it came from, and "POSIX time" the standard that defines it. All three mean the same count.

Why the epoch is January 1, 1970

Nothing significant happened on that date. It's a round starting point close to when Unix was being developed at Bell Labs in the early 1970s. Choosing a recent date kept the numbers small for the hardware of the time. Once the convention was set it spread far beyond Unix, and today languages, databases and operating systems on every platform count from the same moment, which is what makes a timestamp portable between them.

Seconds vs milliseconds: 10 digits or 13

Standard Unix time is in seconds, but JavaScript's Date.now(), Java's System.currentTimeMillis() and many web APIs use milliseconds since the same epoch. The digit count tells you which one you have:

DigitsUnitExample for 2025-01-01 00:00:00 UTC
10Seconds1735689600
13Milliseconds1735689600000
16Microseconds1735689600000000
19Nanoseconds1735689600000000000

Every 10-digit seconds value falls between 2001-09-09 01:46:40 UTC (1000000000) and 2286-11-20 17:46:39 UTC (9999999999), and 13-digit millisecond values cover the same span. So for any date in that window, the digit count is a reliable test.

Mixing the units fails loudly in one direction and quietly in the other. Read a 2026 millisecond value as seconds and you land around the year 57,971. Go the other way, as in new Date(1735689600) in JavaScript, which expects milliseconds, and you get 1970-01-21T02:08:09.600Z: a plausible-looking date that's simply wrong.

How to convert a Unix timestamp

Each snippet below was run against the timestamp 1735689600 and returned 2025-01-01 00:00:00 UTC, or turned that date back into 1735689600.

JavaScript

Python

Always pass a time zone. Without tz=, fromtimestamp() returns the server's local time, and a naive datetime passed to .timestamp() is assumed to be local time too, so the same code gives different answers on machines set to different zones.

SQL

Excel

Excel stores dates as a count of days, so divide seconds by 86,400 and add the epoch:

=A2/86400 + DATE(1970,1,1)          seconds to date
=A2/86400000 + DATE(1970,1,1)       milliseconds to date
=(A2 - DATE(1970,1,1)) * 86400      date to seconds

Format the result cell as a date and time, for example yyyy-mm-dd hh:mm:ss, or you'll see a plain number like 45658. The result is in UTC, because Excel dates carry no time zone. To show US Eastern Standard Time, subtract 5/24. Using DATE(1970,1,1) rather than the hard-coded serial number 25569 keeps the formula correct in workbooks that use the 1904 date system. We tested these formulas in LibreOffice Calc, which uses the same date-serial approach.

Command line

date +%s prints the current timestamp. To convert one, GNU/Linux uses date -u -d @1735689600 and macOS/BSD uses date -u -r 1735689600.

Leap seconds: Unix time ignores them

POSIX, the standard that defines Unix time, says that "each and every day shall be accounted for by exactly 86400 seconds." Inserted leap seconds are simply not counted. The Linux time(2) manual page puts it this way: Linux systems normally follow the POSIX requirement that the value ignore leap seconds, so it "is not the same as the actual number of seconds" since the epoch.

In practice, when a leap second occurs, systems either repeat a timestamp or "smear" the extra second by running the clock slightly slow for several hours. The payoff is simple math: dividing any timestamp by 86,400 gives whole days since 1970, and every day boundary is a multiple of 86,400. The cost is that subtracting two timestamps across a leap second can be off by one second from the true elapsed time.

The gap is small and has stopped growing for now. According to IERS Bulletin C (republished here), UTC has been 37 seconds behind International Atomic Time (TAI) since January 1, 2017. In 2022 the General Conference on Weights and Measures decided that the maximum allowed difference between UT1 and UTC will be increased in, or before, 2035, which is expected to end leap seconds as they work today.

The Year 2038 problem

Older systems store Unix time as a signed 32-bit integer. The largest value it can hold is 231 − 1 = 2,147,483,647, and this Python snippet shows exactly when that runs out:

from datetime import datetime, timedelta, timezone
epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
print(epoch + timedelta(seconds=2**31 - 1))   # 2038-01-19 03:14:07+00:00
print(epoch + timedelta(seconds=-2**31))      # 1901-12-13 20:45:52+00:00

So the last representable moment is 03:14:07 UTC on Tuesday, January 19, 2038. One second later, a signed 32-bit counter wraps around to −2,147,483,648, which reads as 20:45:52 UTC on December 13, 1901. In US Eastern time the overflow moment is 10:14:07 p.m. on Monday, January 18, 2038.

The risk sits mostly in embedded devices, old file formats and database columns declared as 32-bit integers, not in modern languages. JavaScript, for example, handles 2147483648 seconds (2038-01-19 03:14:08 UTC) without trouble.

Negative timestamps: dates before 1970

A negative timestamp counts backward from the epoch. -1 is 1969-12-31 23:59:59 UTC and -86400 is 1969-12-31 00:00:00 UTC. PostgreSQL, SQLite, Python and JavaScript all accept negative values; we checked each one.

Watch the rounding when you convert negative milliseconds to seconds. −1,500 ms is 1969-12-31 23:59:58.500 UTC, so the whole-second value is −2. Math.floor(-1500 / 1000) gives −2, which is correct, but Math.trunc() or Python's int(-1.5) gives −1, half a second in the future. Python's floor division, -1500 // 1000, gives −2.

Convert a timestamp

Auto-detects seconds vs. milliseconds and shows both UTC and your local time.

Timestamp Converter →

Notable timestamps

TimestampUTC date and timeWhy it's notable
01970-01-01 00:00:00The epoch itself
10000000002001-09-09 01:46:40First 10-digit timestamp
12345678902009-02-13 23:31:30A popular developer milestone
17356896002025-01-01 00:00:00Start of 2025
17672256002026-01-01 00:00:00Start of 2026
20000000002033-05-18 03:33:202 billion seconds
21474836472038-01-19 03:14:07Largest signed 32-bit value
-21474836481901-12-13 20:45:52Where a 32-bit value wraps to after overflow

Timestamps vs ISO 8601 strings

APIs often send dates as strings like 2025-01-01T00:00:00Z, a format from ISO 8601 that RFC 3339 profiles for internet use. The trailing Z means UTC, and an offset like -05:00 means five hours behind UTC. Strings are easier to read in logs. Integers are smaller, sort correctly as numbers, and can't carry an ambiguous time zone. Many systems store integers and display strings.

Where you'll see Unix time

Frequently asked questions

What is epoch time?

Epoch time is another name for Unix time: the number of seconds since the Unix epoch, 00:00:00 UTC on January 1, 1970, not counting leap seconds. For example, 1735689600 is 2025-01-01 00:00:00 UTC.

Is a Unix timestamp always in UTC?

Yes. The number counts seconds from a fixed UTC moment and has no time zone of its own. A time zone is applied only when the timestamp is shown as a local date and time, so the same value displays differently in New York and Tokyo while meaning the same instant.

How can I tell if a timestamp is in seconds or milliseconds?

Count the digits. For dates between 2001 and 2286, a seconds timestamp has 10 digits and a milliseconds timestamp has 13. JavaScript's Date.now() returns milliseconds, so divide by 1,000 to get standard Unix seconds.

What happens on January 19, 2038?

At 03:14:07 UTC on January 19, 2038, a signed 32-bit timestamp reaches its maximum of 2,147,483,647. One second later it wraps to -2,147,483,648, which reads as December 13, 1901. Systems that store time as 64-bit integers are not affected.

Does Unix time count leap seconds?

No. POSIX defines every day as exactly 86,400 seconds, so inserted leap seconds are not counted. This keeps date arithmetic simple, at the cost of a timestamp difference being off by one second across a leap second.

Can a Unix timestamp be negative?

Yes. A negative timestamp is a moment before 1970. For example, -86400 is 1969-12-31 00:00:00 UTC. When converting negative milliseconds to seconds, round down with floor rather than truncating, or the result will be off by one second.

How do I get the current Unix timestamp in JavaScript?

Use Math.floor(Date.now() / 1000). Date.now() returns milliseconds since the epoch, so dividing by 1,000 and rounding down gives the standard seconds-based Unix timestamp.

Related tools