TabOnly

Unix Timestamp Converter

Convert epoch timestamps to dates and back, in any timezone — including the two local times that are not one instant.

input
result
now
now · seconds1787337236
now · millis1787337236859
ISO 8601 · UTC2026-08-21T18:33:56.859Z
ISO 8601 · local2026-08-21T18:33:56Z

A timestamp is a count, not a date

The Unix epoch — 1970-01-01T00:00:00Z — is the moment Unix time was defined to start, and a Unix timestamp is simply the number of units since then. In seconds, ten digits (for dates after 2001); in milliseconds, thirteen; in microseconds, sixteen; in nanoseconds, nineteen. The unit matters more than it sounds like it should, because a converter that cannot tell them apart does not error on the mismatch — it prints a plausible-looking wrong year. Measured: reading 1516239022000 (a millisecond value, which is 2018) as seconds yields +050017. This tool reads the digit count, says which unit it decided on, and shows what the alternatives would have given. A number is never silently assumed; it is interpreted with the interpretation on the screen.

Timezones are the point

The value is a point in time; the zone is how it reads on a wall clock. That separation is where converters break, and it breaks in real, checkable ways. A zone is not a fixed offset: Asia/Kathmandu moved from +05:30 to +05:45 in 1986, so any converter offering "UTC+5" as a choice gets every Nepali timestamp from before then wrong, and cannot represent Chatham or Lord Howe at all. Offsets are also historical, which is why this page computes the offset for every instant rather than caching one per zone.

And a wall clock does not always read one instant. Twice a year a local time maps to zero instants (spring forward — the time never happened) or two (fall back — it happened twice). Plenty of converters steer around this or pick one silently. This page treats both as the real cases they are: it says the time never existed and shows where the clock jumped to, or it lists both instants and lets you choose.

Do it without this tool

Four languages, four ways to make the mistake, and one honest note about the shell split. First, the shell: GNU and BSD date genuinely use different flags, so it is worth knowing which one you are on.

shell · GNU (linux), BSD (macOS)
# GNU coreutils (Linux)
date -d @1516239022 -u        # Thu Jan 18 01:30:22 UTC 2018

# BSD date (macOS has no GNU date): -r, not -d
date -r 1516239022 -u         # Thu Jan 18 01:30:22 UTC 2018

# the other direction (both: epoch seconds as of now)
date -d "$(date +%s -d '2018-01-18 01:30:22')" -u   # GNU
date -j -f '%Y-%m-%d %H:%M:%S' '2018-01-18 01:30:22' +%s   # BSD
python · the naive fromtimestamp bug
from datetime import datetime, timezone

ts = 1516239022

# Naive: format in the machine's local zone. On a UTC+2 host this prints 03:30,
# silently applying a zone that is NOT in the timestamp. That's the bug.
print(datetime.fromtimestamp(ts))                    # 2018-01-18 03:30:22

# Aware: the instant, in UTC. This is the one that's actually 1516239022.
print(datetime.fromtimestamp(ts, tz=timezone.utc))   # 2018-01-18 01:30:22+00:00

# round trip: a datetime -> epoch seconds
dt = datetime(2018, 1, 18, 1, 30, 22, tzinfo=timezone.utc)
print(int(dt.timestamp()))                           # 1516239022
sql · postgres vs mysql differ in name and type
-- Postgres: to_timestamp returns timestamptz (seconds)
SELECT to_timestamp(1516239022);            -- 2018-01-18 01:30:22+00

-- MySQL: FROM_UNIXTIME (seconds), a DATETIME in the session zone
SELECT FROM_UNIXTIME(1516239022);

-- MySQL: the same instant, psql-style. Prefer these for BI/ETL.
SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 1516239022 * INTERVAL '1 second';  -- Pg
SELECT TIMESTAMP '1970-01-01 00:00:00 UTC' + INTERVAL 1516239022 SECOND;     -- MySQL
javascript · the * 1000 everyone forgets
// The Date constructor takes *milliseconds*, not seconds — the * 1000 is the whole job.
new Date(1516239022 * 1000).toISOString();   // '2018-01-18T01:30:22.000Z'

// the other direction (Math.floor: fractional microseconds must not round up)
Math.floor(Date.now() / 1000);               // epoch seconds

// a string back to epoch millis (date-only parses as UTC — see the FAQ)
Date.parse('2018-01-18')                     // 1516060800000

The standards, which is which

Three documents govern the boxes above, and conflating them is where the prose gets it wrong. The POSIX time_t defines the epoch and the count: seconds since 1970-01-01T00:00:00Z, with the leap-second rule from the FAQ. RFC 3339, not "ISO 8601", is the format engineers mean when they write 2018-01-18T01:30:22Z — it is a profile of ISO 8601 that requires the T, requires a timezone designator (a Z or an offset like +02:00), and forbids the comma decimal separator that ISO 8601 allows. The IANA timezone database is what actually knows that Kathmandu changed offset in 1986: it is a published, versioned dataset that updates several times a year, and your browser ships a copy of it. That is why this page's zone list is never hardcoded — it reads Intl.supportedValuesOf('timeZone') from the platform, so a new zone name appears here the day the browser knows it.

FAQ

Why does 13 digits turn into a date in the year 50017?

A millisecond value read as seconds. 1516239022000 is 2018 in milliseconds; read as the same unit you'd give a ten-digit number, it's the year 50017. The page infers the unit from the digit count and shows the alternatives.

Is a Unix timestamp always UTC?

Yes. The timestamp is elapsed seconds since the epoch, period — the zone only ever changes how it is displayed, never the number. Switch the zone control above and the epoch rows stay put. It is the same count wherever it turns up: a JWT's exp, nbf and iat are these seconds too, so “why does my token say expired” is answered by pasting the number here or by reading the whole thing on the jwt-debugger page, which does the same arithmetic.

What actually happens in 2038?

The signed 32-bit time_t overflows at 2147483647: 2038-01-19T03:14:07Z. A naive 32-bit system wraps to 1901 the next second; 64-bit systems are unaffected. This page names the boundary when a value is near it.

Does Unix time count leap seconds?

No. Unix time skips leap seconds, so a wall clock showing 23:59:60 has no corresponding timestamp, and this page rejects it with that explanation rather than rolling it forward.

What does a local time that "happens twice" mean — and which one did my database store?

The clock repeated an hour. Both instants are rendered as rows here; which one your database stored depends on whether it read the clock before or after the transition. Store UTC on write and format on read.

Why do new Date("2018-01-18") and new Date("2018-01-18T00:00") differ?

The ES spec reads date-only strings as UTC and date-time strings without an offset as local. Two strings differing only by a time component can land hours apart. This page states which rule it applied instead of picking silently.

related tools