Search tools

Developer guides

Unix timestamp in seconds or milliseconds? How to tell and convert

A date that lands in 1970, or tens of thousands of years from now, is almost always a unit mix up. Here is how to spot seconds and milliseconds at a glance and convert safely in any language.

Unix time is simple on paper: the number of seconds since midnight UTC on 1 January 1970. In practice you meet it in at least two units, and mixing them up produces dates that are wildly wrong yet perfectly valid, so nothing crashes to warn you.

Tell them apart by length

For any date in recent decades, the number of digits gives the unit away:

Digits Unit Example Where you see it
10 Seconds 1767225600 Unix tools, Python, PHP, Go, most databases
13 Milliseconds 1767225600000 JavaScript, Java, many JSON APIs
16 Microseconds 1767225600000000 PostgreSQL internals, some logging tools
19 Nanoseconds 1767225600000000000 Go’s UnixNano, InfluxDB, tracing tools

All four examples are the same moment, midnight UTC on 1 January 2026. Timestamps in seconds stay at 10 digits from 2001 until 2286, so a 10 digit value today is seconds. The Unix timestamp converter applies exactly this rule and tells you which unit it assumed.

The two classic bugs

Seconds read as milliseconds. JavaScript’s Date expects milliseconds. Hand it a 10 digit value and you get a moment about three weeks after the epoch:

new Date(1767225600)          // Wed Jan 21 1970, which is wrong
new Date(1767225600 * 1000)   // Thu Jan 01 2026, which is right

Milliseconds read as seconds. Going the other way, a 13 digit value read as seconds lands tens of thousands of years in the future. Python refuses to build a date that far out and raises an error instead:

from datetime import datetime, timezone
datetime.fromtimestamp(1767225600, tz=timezone.utc)     # 2026-01-01 00:00:00+00:00
datetime.fromtimestamp(1767225600000, tz=timezone.utc)  # error: year out of range

If you see January 1970, or a year in the tens of thousands, check the unit before anything else.

Converting between them

Multiply seconds by 1,000 to get milliseconds, and divide milliseconds by 1,000 to get seconds. When dividing, round down: that keeps you on the second the event actually happened, while rounding to nearest can push a time into the next second.

const ms = Date.now();                 // milliseconds
const seconds = Math.floor(ms / 1000); // seconds
const date = new Date(seconds * 1000); // and back to a Date
import time
seconds = int(time.time())             # seconds, as a whole number
ms = time.time_ns() // 1_000_000       # milliseconds, with no float rounding
-- PostgreSQL
SELECT to_timestamp(1767225600);            -- seconds to a timestamp
SELECT EXTRACT(EPOCH FROM now())::bigint;   -- the current time in seconds

-- MySQL
SELECT FROM_UNIXTIME(1767225600);
SELECT UNIX_TIMESTAMP();

Unix time, epoch time and UTC

“Epoch time” and “Unix time” mean the same thing: a count from the Unix epoch. UTC is something else. It is the time standard a readable date is written in, as in 2026-01-01 00:00:00 UTC. A Unix timestamp has no time zone at all. It is the same number everywhere in the world at the same instant, and a time zone only comes into it when you format the number as a date for someone to read.

That is why timestamps are such a good way to store moments. Two servers in different countries agree on the number without any conversion.

Which unit should you store?

Pick one per system and put it in the name. A column called created_at_ms, or a JSON field called expires_at_seconds, prevents the bug entirely, because the next person never has to guess. Seconds are enough for most records. Use milliseconds when the order of events inside the same second matters, as with messages or audit logs, and keep them in a 64 bit integer, because a 13 digit value does not fit in a 32 bit one.

Negative timestamps and the year 2038

Moments before 1970 have negative timestamps: −86400 is 31 December 1969. Most languages handle them, but some older databases and file formats do not. At the other end, systems that keep seconds in a signed 32 bit integer overflow at 2147483647, which is 03:14:07 UTC on 19 January 2038. Anything storing dates that far ahead, such as long expiry dates or loan schedules, should use 64 bit values now rather than later.

Read next