Unix Timestamp Converter
Convert a Unix timestamp — the number of seconds since 1 January 1970 UTC — to a readable date and back, in your browser.
| Event | Unix Timestamp (s) | Date |
|---|---|---|
| Unix Epoch Start | 0 | January 1, 1970 00:00:00 UTC |
| Y2K | 946684800 | January 1, 2000 00:00:00 UTC |
| Today (start of day) | — | — |
| Y2K38 Problem | 2147483647 | January 19, 2038 03:14:07 UTC |
| Year 2100 | 4102444800 | January 1, 2100 00:00:00 UTC |
What is a Unix Timestamp?
A Unix timestamp is the number of seconds that have elapsed since January 1, 1970 at 00:00:00 UTC — a reference point known as the Unix Epoch. Because it is timezone-independent, Unix timestamps are ideal for storing and comparing times across different systems and regions. A timestamp of 0 represents exactly the epoch start, and negative values represent times before 1970. Because a timestamp counts seconds, subtracting two of them gives elapsed time, not calendar age: 1 March 2000 to 1 March 2001 is 31,536,000 seconds (365 days), and dividing that by an average 365.25-day year comes out just under one. To count whole years, months and days between two dates, use our age calculator, which steps through the calendar instead.
Seconds vs Milliseconds
Traditional Unix timestamps count elapsed seconds and are typically 10 digits long (e.g. 1700000000). JavaScript's Date.now() and many modern APIs return milliseconds instead, producing 13-digit values (e.g. 1700000000000). To convert seconds to milliseconds, multiply by 1000. To convert milliseconds to seconds, divide by 1000 and floor the result.
Unix Timestamp vs ISO 8601
Unix timestamps are compact integers, making them efficient for storage, sorting, and arithmetic. ISO 8601 (e.g. 2024-03-15T09:30:00.000Z) is a human-readable string format that's self-describing and unambiguous. Use timestamps internally in databases and APIs; use ISO 8601 in logs, user interfaces, and anywhere a human might read the value. Some formats accept only one of the two: the Open Graph article:published_time tag must be ISO 8601, so a blog that stores epoch seconds has to convert before writing the tag. Our Open Graph generator flags a Unix timestamp pasted into that field. XML APIs are the other common case: SOAP and other XML services send dates as xs:dateTime values in the same ISO 8601 form, so after running a response through our XML to JSON converter the date fields are still strings that need converting before you can do arithmetic on them. To pull every ISO 8601 date out of a log or payload first, the pattern \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2} with the g flag finds each one in our regex tester, which also previews rewriting them with capture groups.
How to Tell Seconds from Milliseconds at a Glance
Digit count is a reliable heuristic for any timestamp in the modern era, and this tool applies it automatically.
| Digits | Unit | Example | Interpreted as |
|---|---|---|---|
| 10 | Seconds | 1700000000 | 14 Nov 2023 |
| 13 | Milliseconds | 1700000000000 | 14 Nov 2023 |
| 16 | Microseconds | 1700000000000000 | 14 Nov 2023 |
| 19 | Nanoseconds | 1700000000000000000 | 14 Nov 2023 |
Getting the unit wrong produces errors that are absurd rather than subtle, which is the one mercy here. Read a millisecond value as seconds and you land in the year 55,844. Read seconds as milliseconds and everything collapses into January 1970 — the classic "all my records show 1970" bug, and a reliable sign that a value was divided by 1000 one time too many.
Timestamps in Common Languages
The unit each language returns by default is the usual source of confusion at a service boundary.
| Language | Current timestamp | Returns |
|---|---|---|
| JavaScript | Date.now() | Milliseconds |
| Python | time.time() | Seconds (float) |
| PHP | time() | Seconds |
| Go | time.Now().Unix() | Seconds |
| Java | System.currentTimeMillis() | Milliseconds |
| Ruby | Time.now.to_i | Seconds |
| Rust | SystemTime::now() | Duration since epoch |
| PostgreSQL | EXTRACT(EPOCH FROM NOW()) | Seconds (float) |
| MySQL | UNIX_TIMESTAMP() | Seconds |
| Shell | date +%s | Seconds |
When a JavaScript front end sends Date.now() to a Python backend that assumes time.time(), every date lands roughly 50,000 years in the future. Normalising on one unit — seconds is the more common convention for APIs — at the boundary avoids the whole category. If the API in question returns those timestamps inside a JSON body, our YAML and JSON converter is handy for reformatting the payload while you inspect it.
Timestamp Pitfalls Worth Knowing
01111111 11111111 11111111 11111111: a zero sign bit followed by thirty-one ones, so adding one more second sets the sign bit and the value turns negative. You can watch it happen in the hex converter: switch on 32-bit two's complement and the decimal 2147483648 is rejected as out of range, while the hex pattern 80000000 reads back as −2147483648 — 13 December 1901. (Store the digits as text instead and the same timestamp costs ten bytes — our binary translator shows all 80 bits.)
-86400 is 31 December 1969. Plenty of libraries and database drivers mishandle them, so historical dates deserve a test case.
Choosing How to Store Time
Three sensible options, each with a different trade-off:
- 64-bit integer epoch. Compact, sorts and compares trivially, arithmetic is simple, and it is unambiguous. The cost is that it is unreadable to a human eye scanning raw rows.
- ISO 8601 string. Self-describing and readable, sorts correctly as a string when zero-padded and stored in UTC, but uses more space and requires parsing before arithmetic.
- Native timestamp column (
TIMESTAMPTZin PostgreSQL). Usually the best choice: the database handles conversion, and date functions operate directly on the value. Prefer the timezone-aware variant — plainTIMESTAMPdiscards the offset and reintroduces the ambiguity you were trying to avoid.
Whichever you pick, the durable rule is to store instants in UTC and apply the user's timezone only at the point of display. Storing local time is the root cause of the annual crop of daylight-saving bugs, where an hour either repeats or never happens. If you are writing the queries that read those columns, our SQL formatter makes the date arithmetic easier to read.
Frequently Asked Questions
0, null, or an undefined variable coerced to zero. It usually means a field was never populated, or that a millisecond value was divided by 1000 twice.Math.floor(ms / 1000). Flooring rather than rounding keeps you from landing a moment in the future.