Unix Timestamp Converter
Convert epoch time to a human-readable date and back again, in any time zone. Seconds and milliseconds are detected automatically, dates before 1970 work correctly, and everything runs in your browser — nothing is uploaded.
Current Unix time
The counter above ticks once per second and comes from your own device clock. If it looks wrong, your system clock is wrong.
Timestamp → date
Date → timestamp
Batch convert
Paste a column of timestamps — straight out of a log file, a CSV export, or a database dump — and get a table back. Mixed seconds and milliseconds in the same list are handled per line. Up to 500 lines at a time.
How it works
A Unix timestamp — also called epoch time or POSIX time — is a single integer: the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970, known as the Unix epoch. It is not a string, it has no time zone, and it has no formatting. That is exactly why software likes it: one number, unambiguous, easy to compare and to subtract.
Converting that number into something a human can read means answering three questions, which is what this tool does in order.
1. Is the number in seconds or milliseconds?
Nothing in the number itself says which unit it is, so the tool infers it from magnitude. The exact rule used here, so that the behaviour is predictable at the boundary:
If the absolute value is 100,000,000,000 (1011) or greater, it is treated as milliseconds. Below that, it is treated as seconds.
In practice that means a 10-digit number such as 1700000000 is read as seconds, and a 13-digit number such as 1700000000000 is read as milliseconds. 11- and 12-digit values fall on the seconds side of the line.
The threshold is a deliberate trade-off. Read as seconds, 1011 is the year 5138 — no real seconds timestamp is ever that big. Read as milliseconds, 1011 is 3 March 1973 — so millisecond timestamps from 1970 to early 1973 are the one range that gets misread. If you are working with that era, or with any value where the guess is wrong, use the Seconds or Milliseconds radio buttons to force the unit. The label under the input always tells you which unit was applied and whether it was detected or forced.
2. What instant does it point to?
The number is multiplied by 1,000 if it was in seconds, then handed to the JavaScript Date object, which stores time as a double-precision float of milliseconds relative to the epoch. Negative values are perfectly legal and mean "before 1970": -86400 is exactly one day before the epoch, 31 December 1969. Many converters get this wrong or refuse the input entirely; this one does not.
3. What does that instant look like where you are?
The instant is then rendered in the time zone you pick, using the browser's built-in Intl.DateTimeFormat with an IANA time zone identifier such as Europe/Berlin. This matters more than it sounds. Daylight saving rules change, countries change their offsets, and historical offsets were often not whole hours. Adding a fixed number of hours to UTC — the naive approach — silently produces wrong answers across DST transitions and for any date more than a few years old. Delegating to the platform's time zone database avoids all of that.
The full time zone list comes from Intl.supportedValuesOf('timeZone') where the browser supports it, which is around 400 zones. On older browsers the tool falls back to a shorter curated list. Either way the data ships with your browser — no network request is made.
Output formats
- ISO 8601 —
2023-11-14T17:13:20-05:00. Sortable, machine-readable, carries the offset. This is what you want in an API payload or a config file. - ISO 8601 (UTC) — the same instant with a
Zsuffix, which is the canonical form for storage and logging. - RFC 2822 —
Tue, 14 Nov 2023 17:13:20 -0500. The format used in email headers and HTTP-adjacent contexts. - Human readable —
Tuesday, 14 November 2023 at 17:13:20 EST, for pasting into a ticket or a message to a colleague. - Relative — "2 years ago", "in 12 years". Useful sanity check: if a timestamp you expected to be recent reads "55 years ago", you almost certainly have a unit problem.
- ISO week date and day of year — for anyone reconciling against weekly reporting periods.
Worked examples
1. A 10-digit timestamp from an application log
Your log line reads {"ts":1700000000,"level":"error"}. Paste 1700000000 into the converter. It is under 1011, so it is read as seconds.
Input 1700000000
Detected seconds (10 digits)
UTC 2023-11-14T22:13:20Z
New York 2023-11-14T17:13:20-05:00
Tokyo 2023-11-15T07:13:20+09:00
RFC 2822 Tue, 14 Nov 2023 22:13:20 +0000
Note that the same instant is on 14 November in New York and already 15 November in Tokyo. This is the single most common source of "the report is off by a day" bug reports — the timestamp is fine, the rendering zone differs.
2. A negative timestamp — a date before 1970
Birth dates, historical records and some database sentinel values land before the epoch. Enter -86400:
Input -86400
Detected seconds
UTC 1969-12-31T00:00:00Z
Human Wednesday, 31 December 1969 at 00:00:00 UTC
86,400 is the number of seconds in a day, so minus one day from the epoch is 31 December 1969. Try -1 as well: it is 1969-12-31T23:59:59Z, one second before the epoch. If another tool shows you Invalid Date, 1970-01-01, or a wildly wrong year for these inputs, it is treating the value as unsigned.
3. A 13-digit value — milliseconds from JavaScript or Java
Date.now() in JavaScript and System.currentTimeMillis() in Java both return milliseconds, not seconds. Enter 1700000000000:
Input 1700000000000
Detected milliseconds (13 digits)
UTC 2023-11-14T22:13:20Z
Exactly the same instant as example 1, because 1,700,000,000 seconds is 1,700,000,000,000 milliseconds. Now force the Seconds radio button with the same input and the answer becomes +055840-11-08T22:13:20Z — the year 55,840. Seeing an absurd far-future year is the signature of feeding milliseconds to a function that expects seconds.
4. The 2038 boundary
Enter 2147483647, the largest value a signed 32-bit integer can hold:
Input 2147483647
UTC 2038-01-19T03:14:07Z
Human Tuesday, 19 January 2038 at 03:14:07 UTC
One second later, 2147483648, is 2038-01-19T03:14:08Z here — this tool has no 32-bit limit. On a system that stores time_t as a signed 32-bit integer, that same increment wraps around to -2147483648, which is 13 December 1901. See the FAQ below for what that means in practice.
5. Going the other way — building an API query
An API wants a since parameter in epoch seconds and you need "midnight on 1 March 2024, Berlin time". Set the time zone selector to Europe/Berlin, enter 2024 / 3 / 1 / 0 / 0 / 0 in the date fields, and read off:
Unix seconds 1709247600
Unix milliseconds 1709247600000
Same instant UTC 2024-02-29T23:00:00Z
Berlin was on CET (UTC+1) on that date, so local midnight on 1 March is 23:00 UTC on 29 February — a leap day, no less. Hand-computing this is exactly how off-by-one-day bugs are born.
Frequently asked questions
What exactly is the Unix epoch?
The Unix epoch is the instant 1970-01-01T00:00:00Z — midnight UTC at the start of 1 January 1970. It was chosen by the developers of early Unix as a convenient recent reference point; there is no deeper significance to the date. Every Unix timestamp is an offset from that moment, positive for after and negative for before.
How do I tell whether a timestamp is in seconds or milliseconds?
Count the digits. A present-day timestamp in seconds has 10 digits (10-digit values cover 2001 through 2286). The same instant in milliseconds has 13. Microseconds give 16 digits and nanoseconds 19 — this tool handles seconds and milliseconds directly; for microseconds divide by 1,000,000 and for nanoseconds by 1,000,000,000 first, or simply drop the last 3 or 6 digits to get milliseconds.
The other giveaway is the answer itself. If a timestamp you expect to be recent renders as 1970, you gave seconds to something expecting milliseconds. If it renders as the year 55,840, you did the reverse.
What is the year 2038 problem?
Traditional Unix systems store time in a time_t value that is a signed 32-bit integer counting seconds. The largest value it can hold is 2,147,483,647, which is 2038-01-19T03:14:07Z. One second later the value overflows into negative territory and the date reads 13 December 1901. Any system still using 32-bit time_t at that point will compute wrong durations, sort records backwards, or crash.
Most modern systems have already moved to 64-bit time_t, which pushes the limit roughly 292 billion years out. The remaining risk is concentrated in embedded devices, old binary file formats, database columns declared as 32-bit integers, and network protocols that pin the field width. Note that it is not a purely future problem: code doing 20-year date arithmetic has been crossing the boundary since 2018.
JavaScript is not affected. It stores time as a double-precision float of milliseconds, giving an exact integer range of ±253 milliseconds, deliberately clamped by the language specification to ±8,640,000,000,000,000 ms — about ±273,790 years around 1970. This tool inherits that range.
Can a Unix timestamp be negative?
Yes. Negative values represent instants before 1 January 1970 and are entirely valid. -86400 is 31 December 1969, -2208988800 is 1 January 1900. Plenty of libraries and converters mishandle them — either rejecting the minus sign or reinterpreting the value as a huge unsigned number — so it is worth testing any date pipeline with a pre-1970 value if you handle historical data.
Does a Unix timestamp store a time zone?
No, and this is the most important thing to internalise. A timestamp is an absolute instant, always measured against UTC. The time zone lives entirely in the presentation layer. 1700000000 is simultaneously 22:13 in London, 17:13 in New York and 07:13 the next morning in Tokyo — one number, three renderings, no conversion of the underlying value.
The practical consequence: store timestamps (or UTC), never local wall-clock strings without an offset. Convert to local time only when you display.
Why does another converter show a time one hour different from yours?
Almost always daylight saving. If a tool applies a fixed UTC offset instead of a real time zone, it gets summer dates wrong in winter and vice versa. "UTC−5" is not the same as America/New_York — the latter is −5 in January and −4 in July. This tool always resolves via the IANA time zone database built into your browser, so DST and historical rule changes are applied correctly for the specific date in question.
The other possibility is that one of the two tools is using your system time zone while the other is using UTC. Check the zone selector.
What about leap seconds?
Unix time deliberately ignores them. A Unix day is defined as exactly 86,400 seconds, so when a leap second is inserted the timestamp either repeats a value or is smeared over a period, depending on the system. The upshot is that Unix time is not a true count of elapsed SI seconds since 1970 — it is off by the 27 leap seconds inserted so far. For nearly every application this is irrelevant, but it means you should not use Unix timestamp differences for high-precision interval measurement across a leap second. Use a monotonic clock for that.
What is the largest and smallest value this tool accepts?
±8,640,000,000,000,000 milliseconds, the range JavaScript guarantees — roughly 20 April 271,821 BC to 13 September 275,760 AD. In seconds mode that is ±8,640,000,000,000. Anything beyond it produces a clear out-of-range message rather than a nonsensical date. Non-numeric input is rejected outright; the tool will never render Invalid Date or NaN.
I entered a local time that does not exist. What happens?
On the morning a region springs forward, an hour of local wall-clock time simply never occurs — 02:30 does not exist on 10 March 2024 in New York. If you enter such a time in the date-to-timestamp panel, the tool shifts it forward past the gap and tells you it did so. In the reverse case, when clocks fall back and a local time occurs twice, it picks the earlier of the two instants and warns you that the input is ambiguous. Both cases are flagged rather than silently resolved.
Is any of my data sent to a server?
No. Every conversion, including batch mode, runs as JavaScript in your browser. There is no API to call and no server-side processing, so the values you paste in are never uploaded or logged — you can save the page, open it with the network disconnected, and it still converts. Timestamps in logs are frequently sensitive; they never leave your machine here.
Use cases and limitations
What this is good for
- Reading logs. Application logs, nginx access logs, syslog and JSON structured logs frequently carry raw epoch values. Paste a column into batch mode and get a readable table.
- Debugging APIs. JWT
expandiatclaims, OAuth token expiry, webhookcreatedfields and rate-limit reset headers are all epoch seconds. Checking whether a token is actually expired takes two seconds here. - Database work. Building a
WHERE created_at > ?bound, or sanity-checking a migration that converted aDATETIMEcolumn to an integer. - Cross-team communication. Turning "the incident started at 1700000000" into "17:13 New York time" so the people in the call understand each other.
- Spotting unit bugs. The auto-detect label plus the relative time make seconds/milliseconds mix-ups obvious immediately.
Where it stops
- Leap seconds are not modelled. As above — fine for scheduling and logging, not for metrology.
- Time zone data is your browser’s. If a country changes its DST rules and your browser has not been updated, conversions for future dates in that zone may be stale. This affects every client-side tool equally; keep your browser current.
- Historical dates are approximate before about 1900. Local mean time offsets were not whole minutes, and the Gregorian calendar was adopted at different times in different places. The tool uses the proleptic Gregorian calendar throughout, as the IANA database does.
- No microsecond or nanosecond input. Divide first. Fractional seconds are accepted (
1700000000.25works) and shown to millisecond precision. - Batch mode caps at 500 lines per run, to keep the page responsive. Convert in chunks for larger files.
- It is a converter, not a scheduler. It will not do calendar arithmetic like "the third Tuesday of next month".