Engineering guide

What Is a Unix Timestamp? Epoch Time Explained Simply

What is a Unix timestamp? Learn how epoch time works, seconds vs milliseconds, how to convert it to a date, time zone pitfalls, and the Year 2038 problem.

A clock face beside a timeline that starts at zero and counts forward with a row of digit blocks

Open a database, an API response, or a log file and you will sooner or later meet a number like 1700000000 where a date should be. That number is a Unix timestamp, and it is one of the most common ways computers record a moment in time.

This guide explains what a Unix timestamp is, why seconds and milliseconds cause so many bugs, how to convert a timestamp to a readable date, how time zones and leap seconds fit in, and what the Year 2038 problem really is. It draws on Mozilla's documentation, the POSIX standard, RFC 3339, and Wikipedia's article on the Year 2038 problem, all linked at the end.

The short answer: a Unix timestamp is the number of seconds that have passed since 00:00:00 UTC on 1 January 1970, a moment called the Unix epoch. JavaScript and many web APIs count milliseconds instead of seconds.

What is a Unix timestamp?

Mozilla defines Unix time as a method to represent a timestamp, usually defined as the number of seconds since the beginning of the Unix epoch, which is January 1st, 1970, at midnight UTC. A timestamp is therefore just a counter: zero is the epoch itself, and every second after it adds one.

The values are easy to check. Each of the following has been calculated and confirmed with standard date functions.

  • 0 is 1970-01-01 00:00:00 UTC, the epoch itself.
  • 86400 is 1970-01-02 00:00:00 UTC, exactly one day later.
  • 31536000 is 1971-01-01 00:00:00 UTC, one 365-day year later.
  • 1000000000 is 2001-09-09 01:46:40 UTC.
  • 1700000000 is 2023-11-14 22:13:20 UTC.

Why do computers use timestamps?

A single number sidesteps the ambiguity of written dates. It has no month-day or day-month order, no language, no daylight saving rule, and no time zone, so two systems can exchange it without arguing about format.

It is also convenient to work with. Sorting events is just sorting numbers, and subtracting one timestamp from another gives the seconds between two moments. Timestamps are compact too, which is why databases, logs, file systems, and APIs favor them.

Seconds vs milliseconds

The traditional Unix timestamp counts seconds, but Mozilla points out that on the web platform, Unix time is given as the number of milliseconds since the beginning of the epoch. JavaScript's Date object stores a single numeric timestamp in milliseconds, and Date.now() returns the current value, which is why JavaScript timestamps look about 1,000 times larger.

For present-day dates there is a handy rule of thumb. A 10-digit timestamp is almost certainly in seconds and a 13-digit one is in milliseconds. This holds for dates from September 2001 until the year 2286.

Mixing the units causes famous bugs. A seconds value such as 1700000000 read as milliseconds lands on 20 January 1970, just under 20 days after the epoch, which is the classic sign that a date has been read in the wrong unit. A milliseconds value read as seconds lands tens of thousands of years in the future.

How to convert a Unix timestamp to a date

Converting is a one-liner in most environments. The only thing to remember is to match the unit: JavaScript wants milliseconds, so multiply a seconds timestamp by 1,000.

  • JavaScript: new Date(seconds * 1000).toISOString() returns a UTC date-time string, and Math.floor(Date.now() / 1000) gives the current time in seconds.
  • Spreadsheets: with a seconds value in A1, the formula =A1/86400+DATE(1970,1,1) returns a date-time, which you should format as a date and time. The result is in UTC.
  • Linux with GNU date: date -d @1700000000 prints the date for that timestamp.
  • macOS: date -r 1700000000 does the same.

Worked example: converting 1700000000 by hand

You can decode a timestamp without any tool, which helps you trust what a converter tells you. A day has 86,400 seconds, so start by dividing the timestamp by 86,400.

1,700,000,000 divided by 86,400 is 19,675 whole days with a remainder of 80,000 seconds. Counting 19,675 days forward from 1 January 1970 lands on 14 November 2023. The remaining 80,000 seconds break down as 22 hours (79,200 seconds), 13 minutes (780 seconds), and 20 seconds, so the time of day is 22:13:20 UTC.

Put together, 1700000000 is 22:13:20 UTC on 14 November 2023. A converter that returns the same answer is using the same arithmetic, and one that returns a different clock time is probably showing your local time zone instead of UTC.

Time zones: a timestamp has none

A Unix timestamp identifies one instant, the same instant everywhere on Earth. It carries no time zone, because it counts from a UTC moment. A time zone only matters when you display the instant as a human-readable date, which is when software converts it to local time.

That is why the safest pattern is to store and transmit UTC timestamps and convert to local time only for display. Mozilla's Date documentation also warns about parsing pitfalls: a date-only string such as 2011-10-10 is interpreted as UTC, while a date-time string without an offset, such as 2011-10-10T14:48:00, is interpreted as local time. The same text can therefore produce different instants on different computers.

Leap seconds: why Unix time is not exact elapsed time

Mozilla notes that leap seconds are ignored in Unix time. The POSIX standard goes further, defining seconds since the epoch as a value that approximates the number of seconds that have elapsed since the epoch, and stating that each and every day is accounted for by exactly 86,400 seconds.

For almost all software this does not matter. It means Unix time is a convenient calendar-based count rather than a physically exact measure of elapsed seconds, which only specialized systems need to worry about.

Dates before 1970 and far in the future

Because most systems store timestamps as signed numbers, dates before the epoch are simply negative values. A timestamp of minus 86400 means one day before 1 January 1970.

Every system has limits. JavaScript's Date can represent only plus or minus 8,640,000,000,000,000 milliseconds from the epoch, from April 20, 271821 BC to September 13, 275760 AD, and anything beyond that becomes an invalid date. Mozilla also describes Date as a legacy object, with the Temporal API as the modern replacement for new code.

The Year 2038 problem

Some systems store Unix time as a signed 32-bit integer, which can hold values only up to 2,147,483,647, or 2^31 minus 1. That number of seconds after the epoch is 03:14:07 UTC on 19 January 2038. One second later, the value overflows and wraps to a large negative number, which these systems read as 20:45:52 UTC on 13 December 1901.

The fix is to use 64-bit time values, which are not expected to overflow for roughly 292 billion years. Progress has been made: Wikipedia notes that Linux kernel 5.6, released in 2020, added 64-bit time support for 32-bit architectures, and the GNU C Library enabled it in version 2.34 in August 2021. The remaining risk lies in older embedded devices, file formats, and databases that still use 32-bit fields, so check any system that stores future dates.

Unix timestamp vs ISO 8601 and RFC 3339 dates

Timestamps are not the only way to record a moment. RFC 3339 defines an Internet profile of ISO 8601 that writes the date and time as text in the form YYYY-MM-DDTHH:MM:SS, with an optional fraction and an offset. The letter Z means UTC, and an offset like -04:00 means local time minus four hours from UTC, so 18:50:00-04:00 is the same instant as 22:50:00Z. A complete example from the RFC is 1985-04-12T23:20:50.52Z.

Neither format is universally better. The right choice is often dictated by the API or system you are working with, so follow its documentation.

  • Unix timestamps are compact, sort as plain numbers, and make duration math a simple subtraction.
  • RFC 3339 and ISO 8601 strings are human readable and can carry a time zone offset.
  • JavaScript's toISOString() converts a Date to a UTC string ending in Z, which is a convenient bridge between the two.
  • Either one is safer than a locale-specific date such as 03/04/2026, which readers in different countries interpret differently.

Common Unix timestamp mistakes

Most timestamp bugs are variations on a handful of mistakes, and knowing them speeds up debugging considerably.

  • Using the wrong unit: dates in January 1970 usually mean seconds were read as milliseconds, and dates tens of thousands of years away mean the opposite.
  • Treating a timestamp as local time: it is a UTC-based instant, so convert for display only.
  • Storing local times without an offset: you cannot reliably convert them to an instant later.
  • Using a 32-bit field for future dates: expiry dates, certificates, and long-term schedules can pass 2038.
  • Parsing ambiguous date strings: stick to RFC 3339 or ISO 8601 formats, which browsers and libraries parse consistently.
  • Assuming exact elapsed seconds: leap seconds are ignored, so do not use Unix time for precision physics or astronomy.

Practical checklist

  • Confirm whether a timestamp is in seconds or milliseconds before converting it.
  • Use 10 digits for seconds and 13 digits for milliseconds as a quick sanity check on current dates.
  • Store and transmit time as UTC, and convert to local time only for display.
  • Prefer RFC 3339 or ISO 8601 strings, ending in Z or with an explicit offset, when you need readable dates.
  • Avoid ambiguous date strings that depend on the reader's locale.
  • Use 64-bit fields for any date that might fall after January 2038.
  • Remember that Unix time ignores leap seconds.

Research and references

This guide was prepared from the authoritative references below.

  1. MDN Web Docs: Unix time
  2. MDN Web Docs: Date
  3. The Open Group: POSIX Base Definitions, Seconds Since the Epoch
  4. RFC 3339: Date and Time on the Internet: Timestamps
  5. Wikipedia: Year 2038 problem