Epoch & Unix Timestamp Converter
Paste a Unix timestamp to get the date, or pick a date to get the timestamp. The unit is worked out from the number — seconds, milliseconds or microseconds — and the tool tells you which it assumed, because getting that wrong is the most common epoch mistake there is.
| Format | Value | Copy |
|---|---|---|
| Unix seconds | |
|
| Unix milliseconds | |
|
| ISO 8601 (UTC) | |
|
| ISO 8601 (your zone) | |
|
| UTC | |
|
| Local | |
|
| Relative | |
Runs in your browser. Nothing uploaded.
How to use it
- Paste a timestamp and every format appears — or pick a date and get the timestamp instead. Both directions are on screen at once.
- Check what unit it assumed. If the number was read as milliseconds when you meant seconds, a note says so and the dropdown overrides it.
- Copy the row you need. The UTC and ISO rows are the safe ones to quote in a bug report.
The live clock at the top is the current timestamp, ticking. Copy it, or press “Use it” to load it below.
Seconds or milliseconds?
This is the reason the tool detects the unit instead of asking you to pick one. It is comfortably the most common epoch bug.
JavaScript’s Date.now() returns milliseconds. Python’s time.time(), PHP’s time(), Go’s Unix() and the overwhelming majority of APIs return seconds. Put one where the other belongs and nothing errors — you just get a date that is wrong by a factor of a thousand.
| Digits | Unit | 1786894200 as this unit |
|---|---|---|
| 10 | Seconds | 16 August 2026 — correct |
| 13 | Milliseconds | 21 January 1970 |
| 16 | Microseconds | 1 January 1970, 00:29 |
The quick check: a present-day timestamp in seconds is 10 digits. Thirteen digits means milliseconds — divide by 1000. Sixteen means microseconds, which you will mostly meet in database columns and tracing systems.
The failure is silent in both directions. Treat seconds as milliseconds and you land in January 1970. Treat milliseconds as seconds and you land around the year 58,000. Neither throws an error anywhere.
What Unix time actually is
A count of seconds since 1 January 1970, 00:00:00 UTC — the Unix epoch.
The date was chosen for convenience, not significance: the engineers building early Unix needed a starting point near the present, and 1970 was a round number just behind them.
The useful property is that it carries no timezone. A Unix timestamp refers to one instant, the same instant for everyone. Two servers on opposite sides of the planet agree on it exactly, with no conversion and no ambiguity about whether you meant EST or EDT. That is why it is what systems store internally, and why a written-out date is what they show you at the last possible moment.
Reference points
| Timestamp | Is |
|---|---|
0 |
1 January 1970, 00:00:00 UTC — a Thursday |
86400 |
Exactly one day later |
1000000000 |
9 September 2001 — the “billennium”, widely celebrated by programmers |
1234567890 |
13 February 2009, another one people marked |
2147483647 |
19 January 2038, 03:14:07 UTC — the 32-bit ceiling |
-86400 |
31 December 1969 |
Useful rules of thumb: a 10-digit timestamp starting 17 is somewhere in the mid-2020s, one starting 16 is the early 2020s, and one starting 9 is the 1990s. That is usually enough to sanity-check a value before converting it.
The 2038 problem
A signed 32-bit integer holds values up to 2,147,483,647. As a Unix timestamp that is 03:14:07 UTC on 19 January 2038.
One second later, a system storing time that way overflows to the most negative value it can hold, and the date reads as December 1901. It is the same class of bug as Y2K, with the same fix: use more bits.
Most modern systems already do. 64-bit time_t is standard on current Linux, macOS and Windows, and it pushes the ceiling roughly 292 billion years out. What remains exposed is the awkward long tail — embedded controllers, industrial equipment, older file formats, some database columns declared as 32-bit integers, and anything storing dates as `int` because it seemed like enough at the time.
If you work with systems that will still be running in 2038, the value worth testing against is 2147483648: one second past the ceiling. This tool flags any timestamp beyond it.
Dates before 1970
They are negative, and they work here.
A surprising number of tools reject a negative timestamp or silently clamp it to zero, which turns every historical date into 1 January 1970. If you are storing birth dates, publication dates or anything else that can predate the epoch, that clamping is a data-corruption bug waiting to happen.
-2208988800 is 1 January 1900. It converts here without complaint.
ISO 8601
The international standard for writing a date and time as text: 2026-08-16T15:30:00Z.
Its best property is that it sorts. Because the components run largest to smallest, sorting ISO strings alphabetically also sorts them chronologically — which means a plain text sort on a log file is a chronological sort, with no parsing at all.
| Part | Means |
|---|---|
2026-08-16 |
Year, month, day, always zero-padded |
T |
Separator between date and time |
15:30:00 |
Hours, minutes, seconds on a 24-hour clock |
Z |
UTC. Pronounced “Zulu” |
+01:00 |
Appears instead of Z for a local time with an offset |
An ISO string with an offset and a Unix timestamp carry the same information. An ISO string with no offset — 2026-08-16T15:30:00 — does not, because nothing says which zone it is in. That form causes real bugs and is worth avoiding in anything stored or transmitted.
Worked example
A log line contains 1786894200 and you need to know when it happened, in London.
- Paste it in. Ten digits, so it is read as seconds.
- Set the timezone to Europe/London.
| Format | Value |
|---|---|
| Unix seconds | 1786894200 |
| Unix milliseconds | 1786894200000 |
| ISO 8601 (UTC) | 2026-08-16T15:30:00Z |
| ISO 8601 (London) | 2026-08-16T16:30:00+01:00 |
Note the two ISO rows differ by an hour and both are correct — London is on British Summer Time in August. Same instant, two ways of writing it. The UTC row is the one to paste into a ticket.
Converting in code
| Language | Now, as a timestamp | Timestamp to date |
|---|---|---|
| JavaScript | Math.floor(Date.now()/1000) |
new Date(ts * 1000) |
| Python | int(time.time()) |
datetime.fromtimestamp(ts, timezone.utc) |
| PHP | time() |
date('c', $ts) |
| Go | time.Now().Unix() |
time.Unix(ts, 0) |
| Java | Instant.now().getEpochSecond() |
Instant.ofEpochSecond(ts) |
| SQL (Postgres) | EXTRACT(EPOCH FROM NOW()) |
TO_TIMESTAMP(ts) |
| Command line | date +%s |
date -d @1786894200 |
The JavaScript row is where the milliseconds trap lives: Date.now() gives milliseconds, and the * 1000 going the other way exists for the same reason. Miss either and you are out by a factor of a thousand.
Why your timestamp shows the wrong date
Five causes, in rough order of frequency.
- Wrong unit. Off by a factor of 1000 in either direction. Covered above, and it accounts for most of them.
- Timezone applied twice. A timestamp is already UTC. Convert it to local time, then apply an offset again, and you are out by the offset. This is endemic in code that mixes a date library with manual arithmetic.
- A string that was never parsed.
"1786894200"as a string, concatenated rather than added, produces nonsense silently in loosely typed languages. - Seconds stored in a 32-bit column. Fine until 2038, then negative. Also fine until someone stores a date in 1901 and it wraps the other way.
- Local midnight assumed to be UTC midnight. They are only the same in UTC+0. Everywhere else, “today” starts at a different instant, which is why daily-aggregate reports so often disagree by a few rows.
Storing time properly
Since this page exists because time handling goes wrong, the short version of doing it right:
- Store UTC. Always. Convert to local only when displaying, at the last possible moment.
- Store the timezone separately if you need to know where an event happened. An offset is not a timezone —
+01:00does not tell you whether it was London in summer or Berlin in winter, and the distinction matters the moment daylight saving shifts. - Use a 64-bit integer or a real timestamp type. Not a 32-bit int, and not a string.
- For future events, store the local time and the zone, not the computed UTC instant. Governments change daylight saving rules with months of notice, and a meeting booked for “09:00 in Chicago next March” should move with the rule change rather than drift an hour.
That last one is the counterintuitive rule and the one most systems get wrong. Past events are instants and belong in UTC. Future events are intentions, and an intention to meet at 9am survives a change to the timezone database in a way that a precomputed timestamp does not.
Leap seconds
Unix time pretends every day is exactly 86,400 seconds long. It isn’t — the Earth’s rotation is irregular, and leap seconds are occasionally inserted to keep clocks aligned with it.
When one is inserted, Unix time repeats a value rather than incrementing. So a Unix timestamp is not a true count of elapsed seconds since 1970; it is about 30 seconds behind atomic time and the gap grows.
For essentially all purposes this does not matter, and the simplification is deliberate: it means any timestamp can be converted to a date with pure arithmetic, no table of historical leap seconds required. If you are doing satellite work or precision timing, you want TAI rather than Unix time.
Related tools
To post a time in a chat where every reader should see their own local version, the Discord timestamp generator wraps the same Unix value in Discord’s format codes. For comparing a time across several places at once, use the time zone converter, and for the gap between two dates the date duration calculator. Scheduled jobs fire on the same instants — the cron expression generator shows the next ten in a timezone you name. JWT tokens carry exp and iat as raw Unix seconds, and the JWT decoder turns those into readable dates for you.
Frequently asked questions
What is a Unix timestamp?
It is the number of seconds since 1 January 1970 at 00:00 UTC, a moment known as the Unix epoch. Because it counts from one fixed instant it means the same thing everywhere on Earth, with no timezone attached, which is why almost every system stores time this way internally.
Is my timestamp in seconds or milliseconds?
Count the digits. A present-day timestamp is 10 digits in seconds and 13 in milliseconds. This tool works it out from the size of the number and tells you which it assumed, so you can override it if the guess is wrong. Getting this wrong is the single most common epoch bug: JavaScript gives milliseconds, most APIs give seconds.
What is the 2038 problem?
Systems that store Unix time in a signed 32-bit integer run out of room at 03:14:07 UTC on 19 January 2038, because 2147483647 is the largest value that fits. The next second overflows to a negative number and the date jumps to 1901. Most modern systems use 64-bit integers and are unaffected, but embedded devices and old file formats are still a real concern.
Can a Unix timestamp be negative?
Yes. A negative value is a moment before 1970, so -86400 is 31 December 1969. Plenty of tools reject negatives or silently clamp them to zero, which quietly corrupts historical dates. This one handles them and says when a value is negative.
What is ISO 8601?
It is the international standard for writing dates and times as text, and it looks like 2026-08-16T15:30:00Z. Because it goes from largest unit to smallest, sorting ISO strings alphabetically also sorts them chronologically. The Z means UTC; an offset such as +01:00 appears in its place for a local time.
Does Unix time count leap seconds?
No, and this trips people up. Unix time pretends every day is exactly 86400 seconds long. When a leap second is inserted, the counter repeats a value rather than incrementing, so Unix time is not a true count of elapsed seconds since 1970 — it is roughly 30 seconds behind atomic time. For almost all purposes this does not matter.
Why does the date change when I change the timezone?
The timestamp does not change — it is the same instant. Only the local rendering changes, and a timestamp near midnight lands on different calendar days in different zones. The UTC and ISO rows stay fixed for exactly this reason, which makes them the safe ones to quote in a bug report.
Is anything uploaded?
No. Every conversion runs in your browser in JavaScript. Nothing is sent to a server and nothing is stored, and the page keeps working if you disconnect from the internet after it loads.
Guides that use this tool
Last updated: August 18, 2026