Try it now: Unix timestamp converter and current Unix timestamp.
Unix time in one paragraph
Unix time (POSIX time, epoch time) counts the seconds since 00:00:00 UTC on Thursday, 1 January 1970. That starting point is called the Unix epoch. A moment is stored as a single integer, so it is easy to store, sort, compare and subtract, and it does not depend on a time zone, a calendar or a language.
Why 1970?
Early versions of Unix at Bell Labs needed a fixed starting date for their clocks. The date was moved around in the first years, and the start of 1970 was settled on as a round and recent point. There is no deeper meaning. Because the standard (POSIX) and the C library used it, nearly every programming language and operating system adopted the same epoch.
Seconds, milliseconds and finer units
| Unit | Digits today | Example for 2023-11-14 22:13:20 UTC |
|---|---|---|
| Seconds | 10 | 1700000000 |
| Milliseconds | 13 | 1700000000000 |
| Microseconds | 16 | 1700000000000000 |
| Nanoseconds | 19 | 1700000000000000000 |
The classic Unix timestamp is in seconds. JavaScript and Java use milliseconds. When a value looks like a date in 1970 or in the far future, the unit is almost always the cause. The milliseconds to date converter handles the 13-digit case.
Dates before 1970
Negative numbers count backwards from the epoch. -1 is 23:59:59 UTC on 31 December 1969 and -86400 is 00:00:00 on that day. A signed integer is needed to store them. Some systems, such as those that store the value as unsigned, cannot represent dates before 1970.
Unix time and leap seconds
UTC sometimes adds a leap second so that clocks stay in step with the rotation of the Earth. Unix time does not count them: it assumes that every day has exactly 86,400 seconds. When a leap second happens, Unix time either repeats a second or is smeared over a longer period, depending on the system. The effect is that Unix time is not a perfect count of elapsed SI seconds. For measuring a duration to the second across a leap second, use a monotonic clock. For storing when something happened, Unix time is fine.
The Year 2038 problem
Many older systems store Unix time in a signed 32-bit integer. The largest value it can hold is 2147483647, which is 03:14:07 UTC on 19 January 2038. One second later the value overflows and becomes negative, and a date in 1901 appears. Embedded devices, old file formats and some database columns are at risk.
- A 64-bit integer holds about 292 billion years in each direction, so it ends the problem. Most modern operating systems and languages have moved to it.
- An unsigned 32-bit integer reaches
4294967295, which is 6 February 2106, but it cannot store dates before 1970. - In databases, check the column type. The MySQL
TIMESTAMPtype is limited to 2038-01-19 03:14:07 UTC. UseDATETIMEor a 64-bit integer for later dates.
Unix time, UTC and ISO 8601
| Unix time | ISO 8601 | |
|---|---|---|
| Form | An integer | Text, such as 2023-11-14T22:13:20Z |
| Readable by people | No | Yes |
| Time zone | Always UTC, never stored | Stored as Z or an offset |
| Sorting and maths | Trivial | Sorts as text when the zone is the same |
| Best for | Storage, tokens, logs, calculations | APIs and files that people read |
Good practice for storing time
- Store UTC. Keep the instant as a Unix timestamp or as UTC text, and convert to a time zone only when you show it.
- Keep the unit explicit. Put it in the field name (
created_at_ms) or in the API documentation. - Use 64-bit integers.
- Store the time zone separately when the local wall time matters, for example a meeting at 09:00 in Paris. A fixed offset is not enough, because the offset changes with daylight saving time. Keep the zone name, such as
Europe/Paris. - Do not add 86400 to mean "tomorrow" for local calendar days. Use your language's date library in that time zone.
- Sync clocks with NTP, and allow a small tolerance when you compare timestamps from different machines.
Common bugs
- Seconds treated as milliseconds, or the opposite.
- Parsing a date string without a zone, so each machine reads it as its own local time.
- Showing the UTC value to a user without converting it to their time zone.
- Comparing a timestamp in seconds with one in milliseconds.
- Floating-point rounding: a double holds integers exactly up to 253, which is fine for milliseconds but not for nanoseconds. Use 64-bit integers or strings for those.
Other epochs
Windows FILETIME starts in 1601, .NET ticks in year 1, Apple Cocoa time in 2001 and Excel serial dates in 1899. See the epoch converter for a table and for a converter that shows all of them.