Free Unix Timestamp Converter
Convert between Unix timestamps and human-readable dates.
Timestamp → Date
Date → Timestamp
What Is a Unix Timestamp?
A Unix timestamp (also called epoch time or POSIX time) is the number of seconds that have elapsed since January 1, 1970, 00:00:00 UTC. It's a simple, time-zone-independent way to represent a point in time and is widely used in programming, databases, APIs, and server logs.
For example, the timestamp 1700000000 represents November 14, 2023 at 22:13:20 UTC. JavaScript uses millisecond timestamps (multiply by 1000), while most other languages and APIs use seconds.
Frequently Asked Questions
What date formats can I enter?
You can enter dates in most standard formats: ISO 8601 (2025-12-31T23:59:59Z), common date strings (Dec 31, 2025 11:59 PM), or simple formats like 2025-12-31 23:59:59. The converter uses your browser's built-in date parser.
Does it detect seconds vs milliseconds automatically?
Yes. If the timestamp is larger than 1 trillion, the converter treats it as milliseconds. Otherwise, it treats it as seconds. Both formats are shown in the result table.
What is the Year 2038 problem?
Systems that store Unix timestamps as 32-bit signed integers will overflow on January 19, 2038 at 03:14:07 UTC. Modern systems use 64-bit integers, which can represent dates billions of years into the future. This tool uses JavaScript's Number type, which handles timestamps well beyond 2038.
Why January 1, 1970?
A Unix timestamp is an integer count of seconds elapsed since the Unix epoch, 00:00:00 UTC on Thursday, 1 January 1970. It's a single scalar that uniquely names a moment in time, calendar-agnostic and time-zone-agnostic, the same number names the same instant whether you're in Tokyo or Toronto.
The choice of 1970 was somewhat arbitrary, but not random. The first edition of the UNIX Programmer's Manual (November 1971) defined system time as the number of 60 Hz clock ticks since 1971-01-01. With a 32-bit unsigned integer counting at 60 Hz, the system would only span about 2.26 years before overflow, a problem that became obvious quickly. When the second edition was being prepared in 1972, Ken Thompson and Dennis Ritchie's team switched to counting seconds since 1970-01-01: 32-bit signed integers counting seconds would last roughly 68 years, comfortably past the working life of the engineers writing the code, and the most-recent New Year before the project began made arithmetic easy. There was no committee vote and no IANA-style standards process. The choice stuck because Unix shipped with it, and once a hundred million machines were counting from that moment, no replacement was viable.
POSIX (1988) codified the 1970 epoch as IEEE Std 1003.1's \"Seconds Since the Epoch.\" Today the same epoch underpins C/C++ time_t, Python time.time(), Ruby Time.now.to_i, JavaScript and Java (in milliseconds, see below), Linux/macOS file system timestamps, Bitcoin and Ethereum block headers, and JWT iat/exp/nbf claims. A handful of systems use offset epochs (Windows FILETIME counts 100-nanosecond ticks since 1601-01-01, .NET DateTime ticks since 0001-01-01), but Unix time is the lingua franca for anything that crosses an OS or language boundary.
Seconds vs milliseconds, the most common bug
POSIX defines the timestamp as seconds since the epoch. Every C library, every Python interpreter, every Ruby/Go/Rust/Elixir runtime returns seconds. JavaScript is the famous exception, Date.now() and new Date().getTime() return milliseconds. Java's System.currentTimeMillis() follows the same convention, and several newer database systems (MongoDB BSON's Date type, for instance) also store milliseconds.
The result is a perennial cross-language bug: a Go backend writes 1700000000 (seconds) into a JSON field; a Node.js client passes that into new Date(1700000000), but JavaScript expects milliseconds, so the resulting date is 1970-01-20 instead of late 2023. The fix is new Date(1700000000 * 1000). Conversely, sending a JS millisecond timestamp into Python's datetime.fromtimestamp() yields the year ~55895. Stack Overflow has dozens of variants of \"JavaScript Date showing 1970\" questions, and the mismatch is the root cause in the vast majority.
This converter implements a heuristic: if the input is greater than 1,000,000,000,000, treat it as milliseconds; otherwise treat it as seconds. This works because 1e12 seconds would be the year 33658 AD (well beyond any real-world second-scale input), while 1e12 milliseconds is 9 September 2001 UTC (within the modern range). Microsecond and nanosecond timestamps used in some scientific systems and Linux kernel APIs would push the threshold higher, for those, you'll need to specify the precision explicitly.
The Year 2038 problem (\"Y2K38\")
A signed 32-bit integer can store values from −2,147,483,648 to +2,147,483,647. Interpreted as seconds since 1970-01-01 UTC, the maximum representable moment is 03:14:07 UTC on Tuesday, 19 January 2038. One second later, the counter overflows and wraps to the most-negative value, which decodes as 20:45:52 UTC on Friday, 13 December 1901. Any 32-bit-wide time_t, any database column that stores a 4-byte signed integer for time, and any embedded system whose firmware was written before about 2010 is at risk.
The exposed surface is uncomfortable: industrial PLCs and SCADA controllers with 15-30 year deployment lifecycles installed today; older MySQL TIMESTAMP columns that documented saturate at the 2038 boundary; ext3 filesystems; binary protocol formats (DNSSEC RRSIG fields, NTPv3, several industrial fieldbuses) that pack a 4-byte timestamp; smart TVs and automotive infotainment running quietly-installed older 32-bit Linux kernels. The mainstream fix is widening time_t to 64 bits, which extends the maximum to about +292 billion years, past the heat death of the Sun. Linux 5.6 (March 2020) added 64-bit time syscalls to all 32-bit architectures via Arnd Bergmann's y2038 patchset; glibc 2.34 (August 2021) made 64-bit time_t opt-in via _TIME_BITS=64; Debian 13 \"Trixie\" (2025) is the first release with the full archive recompiled. Apple deprecated 32-bit binaries in macOS 10.15 (2019) and iOS 11 (2017), so the consumer fleet is effectively immune.
The remaining risk surface is overwhelmingly embedded and legacy data on disk: a 64-bit kernel reading a 32-bit timestamp column from a legacy database is just as broken as the database itself. Migration is a per-application data-format problem, not just a kernel problem.
JavaScript Date, the field's most-cursed API
JavaScript's Date object was copied wholesale from Java 1.0 in May 1995 during the 10-day sprint Brendan Eich spent writing the original LiveScript. Java itself deprecated most of java.util.Date's methods in JDK 1.1 (1997), but JavaScript inherited them and could not break web compatibility, so they remain. The result is an API where:
- Months are 0-indexed (
new Date(2024, 0, 15)= January 15) but days are 1-indexed. getYear()returns \"year minus 1900\",getYear()for 2024 is 124.getFullYear()was added later to return 2024 directly.Date.parse('2024-03-15')is parsed as UTC midnight;Date.parse('2024/03/15')is local midnight;Date.parse('March 15, 2024')is implementation-defined.- Before ECMAScript 5 (December 2009) parsing was almost entirely implementation-defined, the same input string could yield different
Datevalues across IE, Firefox, Chrome and Safari.
The Temporal API (TC39 Stage 3 since March 2021) is the modern replacement, providing Temporal.Instant, Temporal.PlainDate, Temporal.PlainTime, Temporal.ZonedDateTime and a real Temporal.Duration type. Browser support is rolling out (Firefox Nightly, Safari 18 partial, Chrome behind a flag as of 2024); polyfills work but add ~25 KB. Moment.js was put into maintenance mode by its maintainers in September 2020, for new projects in 2026 the recommendation is Temporal-first if browser support allows, Luxon or date-fns otherwise, and Moment.js never.
When you'd reach for this
- Debugging API responses. Most JSON APIs return timestamps as either Unix integers or ISO 8601 strings, and many mix them. Pasting a number into a converter dozens of times a day is the highest-volume use case.
- Log file analysis. syslog, journald, AWS CloudWatch and most application logs are timestamped in Unix seconds. Engineers copy a timestamp out of a log line and need to know the wall-clock equivalent.
- Database date-column inspection. A one-off
psqlormysqlquery returns1700000000; the database has functions likeFROM_UNIXTIME()but a browser tool is faster for ad-hoc work. - JWT inspection. Decoding an OAuth token shows
\"exp\": 1738367200. Is this token expired? When does it expire? A timestamp converter is the fastest answer. - Blockchain timestamps. Bitcoin's block
nTimeis Unix seconds (overflows in 2106, 4-byte unsigned). Ethereum block timestamps are Unix seconds too. - OS file-system metadata.
ls -l --time-style=+%sprints Unix mtimes;stat -c '%Y' filenamereturns mtime as an integer. Forensic timestamp reconciliation often involves manually decoding. - Certificate
notBefore/notAfterand HTTPIf-Modified-Sinceheaders, all timestamps that occasionally need decoding.
A note about leap seconds
Since 1972, 27 leap seconds have been inserted into UTC to keep wall-clock time aligned with Earth's slowing rotation. The most recent was 31 December 2016 23:59:60 UTC. Unix time does not encode leap seconds, POSIX explicitly says a Unix timestamp pretends every day has exactly 86,400 seconds. Older Linux systems \"repeat\" the last second; Google and AWS use a \"leap smear\" that spreads the extra second over a 24-hour window. Either way, Unix time never reads 23:59:60 in storage, and subtracting two timestamps that span a leap second produces an answer one second short of true SI-second elapsed time. For application code this is invisible. For astronomical or financial-trading software it can matter. In November 2022, the 27th General Conference on Weights and Measures voted to stop inserting leap seconds by 2035, replacing them with a much larger periodic adjustment.
Quick reference
| Timestamp | UTC datetime | Note |
|---|---|---|
| 0 | 1970-01-01 00:00:00 | The epoch |
| 1,000,000,000 | 2001-09-09 01:46:40 | First "billion-second" milestone |
| 1,234,567,890 | 2009-02-13 23:31:30 | "Cool number" celebrated by some devs |
| 1,700,000,000 | 2023-11-14 22:13:20 | |
| 2,000,000,000 | 2033-05-18 03:33:20 | "Two billionth second" |
| 2,147,483,647 | 2038-01-19 03:14:07 | Last second representable in signed 32-bit |
| 4,294,967,295 | 2106-02-07 06:28:15 | Last representable in unsigned 32-bit (Bitcoin's nTime limit) |
| 9,999,999,999 | 2286-11-20 17:46:39 | Last 10-digit timestamp |
More questions
Why does the same timestamp display a different time on my friend's machine?
Because the underlying number is UTC, but the display converts to local time. 1700000000 is 22:13:20 UTC, but 17:13:20 in New York and 06:13:20 next-day in Sydney. The number is the same; only the rendering differs. To rule out time-zone confusion, ask both machines to display in UTC.
What's the difference between Y2K and Y2K38?
Y2K (Year 2000) was a logic problem in application code: many systems stored years as two ASCII digits, so \"00\" became ambiguous between 1900 and 2000. Every application had to be inspected and patched individually; total worldwide remediation spending was estimated at $300-600 billion. Y2K38 is mostly a data-type problem in low-level libraries, recompiling the C library and kernel against 64-bit time_t fixes a huge fraction of the surface for every application that links against them. The remaining hard cases are persisted on-disk data (databases, file metadata, binary protocols) which need data-migration tooling. The conventional wisdom is that 2038 will be a smaller, less newsworthy event than 2000, more localised embedded-device failures, fewer headline outages.
Why does new Date('2024-03-15') sometimes show March 14?
Because that string is parsed as UTC midnight per the ES5 standard, and then displayed in your local time zone. In a UTC-8 zone like US Pacific, UTC midnight on March 15 is 4 PM on March 14 local time, so .getDate() returns 14. The fix in modern code is either new Date('2024-03-15T12:00:00') (which JavaScript parses as local noon when you omit the Z) or, better, the Temporal.PlainDate.from() API once it ships.
Does anything get sent to a server?
No. The conversion is JavaScript arithmetic running locally in your browser. Nothing about the timestamps you enter leaves the page, useful when the values are customer IDs, internal log lines, or session debug data you'd prefer not to upload anywhere. The page works offline once it's loaded.