Unix Timestamps: Convert Epoch Time to a Date (and Avoid the Usual Bugs)

What a Unix timestamp is, how to tell seconds from milliseconds, how to convert epoch time in JavaScript, Python, SQL and the shell, and time zone bugs to avoid.

· 3 min read

A Unix timestamp is the number of seconds since 00:00:00 UTC on January 1, 1970, a moment known as the Unix epoch. It's one plain number with no time zone, which is why databases, logs, APIs and JWTs use it. Turning it into a readable date is easy. Getting it right every time takes knowing a few traps.

What a timestamp looks like

1760000000  →  2025-10-09 08:53:20 UTC

The same number means the same instant everywhere on Earth. It only becomes "8:53 AM" or "4:53 AM" once you choose a time zone to display it in.

Paste any timestamp into the timestamp converter to see it as a UTC date, in your local time and as a relative time like "3 days ago".

Seconds, milliseconds or microseconds?

The most common bug is mixing up units. Different systems count different things:

UnitDigits todayExampleUsed by
Seconds101760000000Unix tools, PHP, Python's time.time() (as a float), JWTs, most APIs
Milliseconds131760000000000JavaScript Date.now(), Java, many JSON APIs
Microseconds161760000000000000PostgreSQL internals, some logging systems

Counting digits is the quickest check. If you treat a millisecond value as seconds, you'll get a date tens of thousands of years in the future. If you treat seconds as milliseconds, you'll land in January 1970. Either one is a sure sign of a unit mix-up.

Converting in code

JavaScript works in milliseconds, so multiply seconds by 1000:

const seconds = 1760000000;
new Date(seconds * 1000).toISOString();  // "2025-10-09T08:53:20.000Z"

Math.floor(Date.now() / 1000);           // current time in seconds

Python:

from datetime import datetime, timezone

datetime.fromtimestamp(1760000000, tz=timezone.utc)
# datetime(2025, 10, 9, 8, 53, 20, tzinfo=timezone.utc)

int(datetime.now(timezone.utc).timestamp())  # current time in seconds

Pass tz=timezone.utc. Without it, fromtimestamp returns a "naive" datetime in the server's local time, which causes bugs when the code moves to a machine with a different time zone.

PostgreSQL:

SELECT to_timestamp(1760000000);               -- timestamptz
SELECT extract(epoch FROM now())::bigint;      -- current time in seconds

MySQL:

SELECT FROM_UNIXTIME(1760000000);
SELECT UNIX_TIMESTAMP();

Shell:

date -u -d @1760000000    # GNU/Linux
date -u -r 1760000000     # macOS/BSD
date +%s                  # current time in seconds

Time zone bugs to watch for

Store UTC, convert at the edges

Keep timestamps, or UTC datetimes, in your database and APIs. Convert to a local time zone only when showing a date to a person. Storing local times leads to ambiguity, because the same wall-clock time happens twice when clocks go back for daylight saving.

Daylight saving gaps

Adding "one day" as 86,400 seconds isn't always the same as "the same time tomorrow". On a daylight saving change, a local day is 23 or 25 hours long. When you mean calendar days, use a date library's calendar arithmetic rather than adding seconds.

"Midnight" depends on where you are

The start of "today" is a different timestamp in Tokyo than in New York. If you group events by day, decide which time zone defines the day, and apply it consistently. The time zone converter helps you compare times across zones.

Leap seconds

Unix time ignores leap seconds: every day is treated as exactly 86,400 seconds. This rarely matters, but it does mean Unix timestamps aren't a precise count of elapsed physical seconds.

The year 2038 problem

Systems that store timestamps as signed 32-bit integers can count up to 2,147,483,647, which is 03:14:07 UTC on January 19, 2038. One second later the value overflows to a negative number and reads as December 1901.

Most modern systems use 64-bit timestamps and are safe for billions of years. The risk is in older embedded devices, legacy databases with 32-bit integer columns, and file formats that fixed the field width long ago. If you're designing a schema today, use BIGINT or a native timestamp type.

Quick reference

  • A Unix timestamp counts seconds since 1970-01-01 00:00:00 UTC.
  • 10 digits is seconds, 13 is milliseconds, 16 is microseconds.
  • JavaScript uses milliseconds, so multiply seconds by 1000.
  • Store UTC and convert to local time only for display.

Got a timestamp to decode? Paste it into the timestamp converter.