2038-01-19T03:14:07Z

How Long Until the Year 2038 Problem?

At 03:14:07 UTC on 19 January 2038, signed 32-bit Unix time runs out of numbers. Systems that still count seconds in a 32-bit integer will wrap around to December 1901.

–Years
–Days
–Hours
–Minutes
–Seconds
Unix time right now
…
Maximum signed 32-bit value
2147483647
Seconds remaining
…
Wraps around to
1901-12-13T20:45:52Z

How far through the 32-bit range we already are

Measured from the Unix epoch on 1 January 1970 to the overflow instant.

…
1970-01-012038-01-19

What happens at 03:14:07 UTC on 19 January 2038

Unix systems track time as a count of seconds elapsed since 00:00:00 UTC on 1 January 1970. For most of computing history that counter was a signed 32-bit integer, and a signed 32-bit integer cannot hold a value above 2,147,483,647.

That many seconds after the epoch lands on 03:14:07 UTC on Tuesday 19 January 2038. One second later the counter overflows. In two's complement arithmetic it does not saturate or throw, it wraps to negative, and code that reads the result without checking will report the time as 20:45:52 UTC on 13 December 1901.

Why the number is 2,147,483,647

A 32-bit signed integer spends one bit on the sign, leaving 31 bits of magnitude. That gives a maximum of 231 minus 1:

2^31 - 1        = 2147483647 seconds
                = 68.05 years
1970-01-01 UTC  + 2147483647s
                = 2038-01-19T03:14:07Z

next second     = -2147483648
                = 1901-12-13T20:45:52Z

The choice was reasonable when it was made. In the early 1970s, 68 years of range on hardware where every byte was expensive was generous. The mistake was not the width, it was assuming the code would be gone by the time the width ran out.

What actually breaks

Not everything, and the failures are less dramatic than a system halting. The characteristic 2038 bug is a piece of date arithmetic quietly producing an answer from the wrong century:

  • Expiry and validity checks that compare a stored timestamp against now, and conclude a certificate or session expired 137 years ago.
  • Sorting and range queries, where wrapped values sort before everything else and silently fall out of result sets.
  • Interval arithmetic, where subtracting two timestamps across the boundary produces an enormous or negative duration.
  • Filesystem and archive metadata that cannot represent the date at all, so it is stored wrong on write rather than misread on read.
  • Embedded controllers in industrial, medical, automotive, and building systems, where the firmware is 32-bit, the vendor is gone, and there is no update path.

The last category is the genuinely hard one. Recompiling a web service is a scheduling problem. Replacing a programmable logic controller welded into a production line is a capital expenditure.

What is already fixed

A great deal, and this is worth stating plainly because the problem is often described as though nothing has been done. Any system running a 64-bit build already uses a 64-bit time_t and is unaffected for about 292 billion years.

Milestones in 64-bit time_t support. All are historical and stable.
ComponentVersionChange
NetBSD6.0 (2012)64-bit time_t on all architectures
OpenBSD5.5 (2014)64-bit time_t on all architectures
Linux kernel5.6 (2020)Completed 64-bit time support for 32-bit architectures
glibc2.34 (2021)Opt-in _TIME_BITS=64 for 32-bit builds

On 32-bit Linux the kernel side and the library side are separate problems. A 5.6 or newer kernel can represent the time correctly, but a 32-bit userspace program still needs to be compiled against a glibc that exposes the 64-bit interfaces, which means building with _TIME_BITS=64 and _FILE_OFFSET_BITS=64. Distributions have been working through this rebuild for years.

What is still exposed

The remaining risk concentrates in places where recompiling is not an option or where the 32-bit width is baked into a format rather than a variable:

  • Storage formats with fixed-width time fields. ext4 inodes of 128 bytes cannot represent dates past 2038. Inodes of 256 bytes carry extra epoch bits and reach 2446. The inode size was fixed when the filesystem was created and cannot be changed in place.
  • Database column types. A MySQL or MariaDB TIMESTAMP column tops out at 2038-01-19 03:14:07 UTC. DATETIME does not have the limit. This is a schema decision made years ago in a lot of production systems.
  • Binary protocols and file formats that specify a 32-bit time field on the wire. Changing those means a format version bump and a compatibility story.
  • Long-lived 32-bit embedded firmware, especially where the toolchain itself predates the fix.

Worth noting for contrast: JavaScript is unaffected. The Date type stores a floating point count of milliseconds and stays exact until around the year 275760. The countdown at the top of this page has no 2038 problem of its own.

The 2036 NTP rollover arrives first

Two years before time_t overflows, a different clock runs out. Network Time Protocol timestamps count seconds since 1 January 1900 in an unsigned 32-bit field. That range ends at 06:28:16 UTC on 7 February 2036, when NTP era 0 rolls into era 1.

NTP was designed with this in mind and the protocol handles eras correctly, but implementations vary in how well they infer which era a timestamp belongs to. Anything that gets its time from the network will meet 2036 before it meets 2038, which makes it the better forcing function for an audit.

It has already broken things

The date on the countdown is when time itself overflows. Systems that do arithmetic forward from today crossed the boundary long ago. Anything calculating a twenty year term hit 2038 back in 2018. Thirty year mortgage schedules reached it in 2008.

This is the practical point that gets missed. Failures do not queue up politely and arrive on the day. They arrive whenever a system first calculates a date past the boundary, which for long-dated financial instruments, certificate lifetimes, and warranty and retention schedules is already happening. If you are going to find a 2038 bug, you will probably find it years before 2038.

How to check your own systems

Start with the width of time_t in the toolchain that actually builds your binaries, which is not always the same as the host you are typing on:

# Userspace word size
getconf LONG_BIT

# Actual width of time_t as your compiler sees it
printf '#include <stdio.h>\n#include <time.h>\n
int main(void){printf("time_t is %%zu bytes\\n", sizeof(time_t));return 0;}' \
  | cc -x c - -o /tmp/tsize && /tmp/tsize

Four bytes means exposed. Eight means safe. For a 32-bit target that reports four, check whether your glibc supports the 64-bit interfaces and rebuild with them enabled:

cc -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 ...

Then audit storage, which is where the problem outlives any recompile:

-- Columns that cannot hold a date past 2038
SELECT table_schema, table_name, column_name
FROM   information_schema.columns
WHERE  data_type = 'timestamp';

# ext4 inode size: 128 means capped at 2038
sudo tune2fs -l /dev/sdXN | grep -i 'inode size'

Finally, test the behaviour rather than reasoning about it. Do this in a container or a disposable virtual machine, never by setting the clock on a live host, since jumping a production system forward fourteen years will expire every certificate and token it holds:

faketime '2038-01-19 03:14:00' ./your-binary

How this page calculates the countdown

The countdown is the difference between the current Unix timestamp and 2,147,483,647, broken into years of 365.25 days, then days, hours, minutes, and seconds. The progress bar is the current timestamp divided by that same maximum, which is the fraction of the signed 32-bit range already consumed.

Every figure comes from your own system clock, so if your machine's time is wrong then so is this page. It was built by Tiempo Software as a single static HTML file with no backend and no tracking of what you run.

Sources and further reading

This page is informational and is not a substitute for auditing your own systems. Command examples are illustrative. Run them in a disposable environment before running them anywhere that matters.