The Year 2038 Problem (Y2K38) Explained
On January 19, 2038 at 03:14:07 UTC, the Unix timestamp 2,147,483,647 — the maximum value of a 32-bit signed integer — will overflow and wrap to a 1901 date. Here is what that means, which systems are affected, how the 64-bit time_t fix works, and how to test your own code.
The overflow in one line
A signed 32-bit integer maxes out at 2,147,483,647. Stored as Unix seconds, that value is 2038-01-19 03:14:07 UTC — and one second later it wraps to -2,147,483,648, which reads as December 13, 1901. Any system that still keeps time in a 32-bit signed integer will jump 137 years into the past at that instant. The fix is a single word: 64-bit. The table below shows which storage types are affected and which are already safe.
| Storage type | Overflows at / max date | Safe past 2038? |
|---|---|---|
| Signed 32-bit time_t / SQL INT | 2038-01-19 03:14:07 UTC | No |
| MySQL TIMESTAMP | 2038-01-19 03:14:07 UTC | No — use DATETIME |
| Unsigned 32-bit | 2106-02-07 06:28:15 UTC | Buys 68 years, not a fix |
| Signed 64-bit time_t / SQL BIGINT | ~292 billion years | Yes |
| 64-bit float (JavaScript, Python) | year 275,760 | Yes |
| MySQL DATETIME (packed fields) | year 9999 | Yes |
What is the Year 2038 problem?
Unix timestamps are traditionally stored as a signed 32-bit integer counting seconds since January 1, 1970 00:00:00 UTC. The maximum value of a 32-bit signed integer is 2,147,483,647 — which corresponds to January 19, 2038 at 03:14:07 UTC. One second after that moment, the integer overflows to -2,147,483,648. Interpreted as a Unix timestamp, that negative value corresponds to December 13, 1901 — sending affected systems nearly 137 years into the past.
- 2^31 − 1 = 2,147,483,647 (maximum 32-bit signed integer)
- 2,147,483,647 as a date = January 19, 2038 03:14:07 UTC
- 2,147,483,647 + 1 overflows to −2,147,483,648 (the most negative 32-bit value)
- −2,147,483,648 as a date = December 13, 1901 20:45:52 UTC
- Local time of overflow varies: 22:14:07 EST on Jan 18, 14:14:07 JST on Jan 19
Which systems are at risk?
The problem affects systems that store timestamps as 32-bit signed integers:
- Embedded systems and microcontrollers with 32-bit time_t
- Legacy C and C++ code compiled for 32-bit targets using time_t or int for timestamps
- Old Linux kernels (before 5.6) on 32-bit hardware still in production
- MySQL TIMESTAMP columns — limited to 2038-01-19; use DATETIME instead
- Some network protocols and file formats that encode timestamps as 32-bit values
- Firmware in industrial control systems and IoT devices with decade-long lifespans
Which systems are safe?
Most modern code and infrastructure is already unaffected:
- Any 64-bit OS — Linux (glibc 2.34+ also fixes 32-bit hardware), macOS, Windows
- Python — timestamps use 64-bit floats, safe well past the year 292 million
- JavaScript — Date uses 64-bit IEEE 754 floats, safe to year 275,760
- Go and Rust — use int64 for time internally, safe for billions of years
- Java — java.time.Instant uses long (64-bit), safe to year ~292 million
- PostgreSQL TIMESTAMP — stores dates beyond 2038 correctly
- MySQL DATETIME — range 1000-01-01 to 9999-12-31, unaffected
MySQL TIMESTAMP and the 2038 ceiling
MySQL has two main date-time column types and they behave very differently around 2038:
- TIMESTAMP is stored as a 32-bit signed Unix integer internally — it overflows at 2038-01-19 03:14:07 UTC
- DATETIME is stored as packed Y/M/D h/m/s fields and supports up to year 9999 — use it for any date that could be after 2038
- TIMESTAMP also implicitly converts to/from the server’s session timezone; DATETIME stores the value as-is
- For raw epoch columns, store BIGINT rather than INT so the value itself cannot overflow
- Audit existing schemas: SELECT TABLE_NAME, COLUMN_NAME FROM information_schema.COLUMNS WHERE DATA_TYPE = "timestamp"
Embedded Linux and 32-bit time_t
The largest remaining Y2038 risk is in long-lived embedded systems: routers, industrial controllers, automotive ECUs, smart meters, and IoT devices that were shipped with 32-bit kernels and may stay in service past 2038. The C library and any custom binary protocols both have to be 64-bit clean.
- glibc gained 64-bit time_t for 32-bit ABIs via the -D_TIME_BITS=64 build macro (glibc 2.34+)
- musl libc has been 64-bit time_t by default since version 1.2.0 (2020)
- Debian, Ubuntu, and OpenWrt have all migrated their 32-bit ports to 64-bit time_t
- Filesystem timestamps are a separate concern: ext2/ext3 use 32-bit times; ext4 supports 64-bit on inodes ≥ 256 bytes
- For hardware still shipping in 2026+, confirm both the C library and any wire formats are 64-bit
How to fix and test for Y2038
The fix is always the same — widen the time to 64 bits — but it has to be applied at every layer that stores or transmits a timestamp: the C library, the database columns, and any binary protocol or file format. The fastest way to find a problem is to move a clock past the boundary in a test environment and watch for dates that land in 1901.
- Compile 32-bit code with -D_TIME_BITS=64 (and -D_FILE_OFFSET_BITS=64) on glibc 2.34+
- Use BIGINT, not INT, for any column that stores raw Unix seconds or milliseconds
- Prefer DATETIME or TIMESTAMPTZ over MySQL TIMESTAMP for dates that can exceed 2038
- In tests, set the system or container clock to 2038-01-19T03:14:08Z and assert dates stay in 2038
- Check wire formats and file headers — a 64-bit OS does not help if the protocol field is 32-bit
Related rollovers: Y2K, GPS, NTP, and 2106
Year 2038 is one of a family of fixed-width time rollovers. Each comes from packing a clock into too few bits, and knowing the dates helps you spot the next one before it ships:
| Rollover | Date | Cause |
|---|---|---|
| Y2K | 2000-01-01 | Two-digit year storage |
| GPS week rollover | 2019-04-06 | 10-bit GPS week counter |
| NTP era rollover | 2036-02-07 | Unsigned 32-bit seconds since 1900 |
| Year 2038 (Y2K38) | 2038-01-19 | Signed 32-bit seconds since 1970 |
| Year 2106 | 2106-02-07 | Unsigned 32-bit seconds since 1970 |
Related references
FAQ
- What is the Year 2038 problem?
- The Year 2038 problem (Y2K38) is a bug where systems using 32-bit signed integers to store Unix timestamps will overflow on January 19, 2038 at 03:14:07 UTC. The maximum value of a 32-bit signed integer is 2,147,483,647. One second later, the integer wraps to -2,147,483,648, which corresponds to December 13, 1901.
- What is the Unix timestamp for January 19, 2038?
- The Unix timestamp for January 19, 2038 at 03:14:07 UTC is 2,147,483,647 — the maximum value of a 32-bit signed integer (2^31 - 1). This is the exact moment the Year 2038 overflow occurs on 32-bit systems.
- How do I fix the Year 2038 problem?
- Store time in a signed 64-bit integer instead of 32-bit. Use 64-bit time_t (build 32-bit code with -D_TIME_BITS=64 on glibc 2.34+), BIGINT instead of INT for epoch columns, and DATETIME instead of MySQL TIMESTAMP. A 64-bit signed time value does not overflow for about 292 billion years.
- Is Y2K38 the same as Y2K?
- No. Y2K (Year 2000 problem) was caused by programs storing years as 2-digit numbers. Y2K38 is caused by storing Unix timestamps as 32-bit signed integers that overflow in 2038. Different root causes, different affected systems.
- What is the Year 2106 problem?
- Year 2106 is the same overflow for unsigned 32-bit timestamps, which run out on February 7, 2106 at 06:28:15 UTC. Switching from signed to unsigned 32-bit buys 68 more years but is not a real fix; 64-bit time is.
- Will the internet break in 2038?
- Probably not significantly. Most internet infrastructure has already migrated to 64-bit systems. The risk is concentrated in embedded systems, legacy IoT devices, and software that has not been updated in decades. Modern operating systems, programming languages, and databases are already safe.