Skip to content
OEWER Tools
How-To

Unix Timestamps Explained: Seconds, Milliseconds, Zones

4 min readBy OEWER Team

What a Unix timestamp counts, how to tell seconds from milliseconds, why it has no time zone, and what the year 2038 problem is about.

In this article
  1. What the number counts
  2. No time zone inside the number
  3. Seconds or milliseconds?
  4. Dates before 1970 and far in the future
  5. The year 2038 problem
  6. Turning a local date into a timestamp
  7. Practical tips
  8. Sources

A Unix timestamp is a single number that stands for a moment in time. It appears in logs, databases, APIs and tokens, and it is easy to misread: is it seconds or milliseconds, and in what time zone? This guide explains what the number counts, how to read it, and the traps that cause dates to be off by hours or by decades.

What the number counts

A Unix timestamp is the number of seconds since the start of 1 January 1970 in UTC, a moment known as the epoch. POSIX, the standard behind Unix-like systems, defines the value as seconds since the epoch and says every day counts as exactly 86,400 seconds. Leap seconds are not counted. The timestamp 0 is 1 January 1970, 00:00:00 UTC, and 1,700,000,000 is 14 November 2023 at 22:13:20 UTC.

No time zone inside the number

A timestamp always refers to a single instant, the same everywhere on Earth. It has no time zone of its own. Time zones only matter when you show it to a person. The instant 1,700,000,000 is 22:13:20 in UTC and 03:43:20 the next morning in India, which is 5 hours 30 minutes ahead. This is why timestamps are good for storing and comparing times, and local dates are good for showing them.

Seconds or milliseconds?

The classic Unix timestamp counts seconds, and today it has 10 digits. JavaScript and many other systems use milliseconds, which gives 13 digits for current dates. Mixing them up is the commonest mistake. Read as seconds, 1,700,000,000,000 would be a date in the year 55,800. Read as milliseconds, 1,700,000,000 would be January 1970, only about 19 days after the epoch. A converter can guess from the size of the number, and the one on this site treats 100 billion or more as milliseconds. When it matters, choose the unit yourself.

  • 10 digits: usually seconds, for dates between 2001 and 2286.
  • 13 digits: usually milliseconds.
  • 16 digits: microseconds, used by some databases.
  • 19 digits: nanoseconds, used by some systems and languages.

Dates before 1970 and far in the future

Timestamps before the epoch are negative. The number -86,400 is 31 December 1969. A JavaScript date can hold up to 8.64 quadrillion milliseconds either side of the epoch, which is roughly the year 275,760 in both directions, so values beyond that are invalid.

The year 2038 problem

Some older systems store the timestamp as a signed 32-bit integer. The largest such number is 2,147,483,647, which is reached at 03:14:07 UTC on 19 January 2038. One second later the counter wraps around to a large negative number, which these systems read as December 1901. Affected places include old file systems, some databases and embedded devices that are hard to update. The fix is to use a 64-bit integer, which lasts about 292 billion years, and most modern systems already do.

Turning a local date into a timestamp

The same clock time in different zones gives different timestamps. Midnight on 1 January 2024 is 1,704,067,200 in UTC, but it is 1,704,047,400 in India, because midnight arrives 5 hours 30 minutes earlier there. Always say which zone a date and time are in. In JavaScript, a date written without a zone is read in the zone of the device for a date-time, but as UTC for a date alone, which is a frequent source of off-by-one-day bugs.

Practical tips

  • Store and send times as UTC timestamps or ISO 8601 strings that end in Z.
  • Convert to a local time zone only when showing the time to a person.
  • Check the number of digits before assuming the unit.
  • Test dates around daylight saving changes in zones that use them.
  • Plan for the 2038 limit if any 32-bit field is involved.

One more habit helps: write the unit and the zone next to every timestamp in code, comments and documentation. A field named created_at tells a reader nothing, while created_at_ms_utc tells them both. When two systems exchange times, agreeing on this once, in writing, prevents the bugs that are hardest to spot, because the dates look plausible but are wrong by five and a half hours or by a thousand years.

Sources

This article was written with AI assistance. How we research and check our articles.

Share

Email

Keep reading