---
title: "The Year 2038 problem: when 32 bits of seconds run out"
url: https://erroneo.us/daily/year-2038-problem/
description: "A signed 32-bit time_t overflows at 03:14:07 UTC on Jan. 19, 2038 and wraps to 1901. 64-bit systems are mostly fine; old formats and devices aren't."
type: daily-entry
section: "Developers"
date_published: 2026-11-03
author: erroneo.us Editors
date_modified: 2026-11-03
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---

# The Year 2038 problem: when 32 bits of seconds run out

> Y2K was about two-digit years. Y2038 is about a counter that runs out of room. Most laptops are already safe; the risk sits in database columns, file formats and devices nobody plans to replace.

*Error of the Day for November 3, 2026 · Developers · by erroneo.us Editors*

- **Wrong:** Y2038 was fixed when everyone moved to 64-bit machines.
- **Right:** 64-bit kernels and libraries are mostly fixed, but any 32-bit timestamp, whether in a database column, file format, protocol or embedded device, still overflows on January 19, 2038.
- **Memory trick:** 2^31 - 1 seconds after 1970 is 2038-01-19 03:14:07 UTC; check where your timestamps are stored, not just the CPU.

## What people get wrong

Unix-like systems keep time as a count of seconds since the Epoch, midnight UTC on January 1, 1970. POSIX defines this as ["Seconds Since the Epoch"](https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap04.html). For decades that count lived in a `time_t` that was a **signed 32-bit integer**. The biggest value it can hold is 2^31 − 1, or 2,147,483,647.

That many seconds after the Epoch is **03:14:07 UTC on Tuesday, January 19, 2038**. One second later the counter overflows and wraps to its most negative value, which a naive system reads as December 13, 1901.

```
>>> datetime.fromtimestamp(2**31 - 1, timezone.utc)
2038-01-19 03:14:07+00:00
>>> datetime.fromtimestamp(-2**31, timezone.utc)
1901-12-13 20:45:52+00:00
```

The common mistake is thinking this was settled when desktops went 64-bit. The CPU was never the issue. The issue is wherever a timestamp gets *stored* in 32 bits.

## Where it still bites

**Database columns.** MySQL's `TIMESTAMP` type has a documented range of ['1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC](https://dev.mysql.com/doc/refman/8.4/en/datetime.html); `DATETIME` runs to the year 9999. A schema designed today with a `TIMESTAMP` "expires_at" column already can't hold a 15-year expiry date.

**Language runtimes on 32-bit platforms.** Python's docs warn that the future cut-off for its `time` functions ["is determined by the C library; for 32-bit systems, it is typically in 2038"](https://docs.python.org/3/library/time.html). On such platforms `localtime()` can raise `OverflowError`.

**Embedded and long-lived hardware.** Routers, industrial controllers, cars and medical devices often run 32-bit chips for decades. LWN notes these [might prove harder to fix as the date approaches](https://lwn.net/Articles/938149/), and argues they should be made 2038-ready when they're deployed.

**Formats and protocols.** Any binary file header, network message or serialized struct with a 32-bit seconds field has the same limit, whatever machine reads it.

**Dates in the future, today.** The bug doesn't wait for 2038. Anything that calculates a date 12 or more years out, such as a mortgage schedule, a certificate expiry or a "never expires" sentinel value, can overflow now.

## What's been fixed

A lot. Linux 5.6 (2020) was the [first mainline kernel that 32-bit systems could use to run past 2038](https://www.phoronix.com/news/Linux-5.6-32-bit-Past-Y2038), provided user space is also built with a 64-bit `time_t`. By 2023, LWN described the kernel as ["mostly free of year-2038 problems,"](https://lwn.net/Articles/938149/) with glibc able to handle 32-bit or 64-bit `time_t` depending on how a program is compiled. The remaining work is in distributions, libraries and applications. That's harder, because changing the size of `time_t` breaks binary compatibility.

## The fix

Wrong: `CREATE TABLE tokens (expires_at ~~TIMESTAMP~~);`

Right: `CREATE TABLE tokens (expires_at DATETIME);` -- or a 64-bit integer of epoch seconds

Why: Store time in types that reach past 2038, then test with dates that do.

- **Use 64-bit time everywhere you store or send it.** Integers of epoch seconds or milliseconds should be `int64`, not `int32`.
- **Grep for the risky types:** `int32` or `uint32` timestamp fields, MySQL `TIMESTAMP` columns, and C `struct`s packed for file formats.
- **When building C code for 32-bit targets**, compile against a C library with 64-bit `time_t` support, and rebuild dependencies the same way.
- **Test with the future.** Fake the clock to 2038-01-19 03:14:08 UTC and to 2040 in your integration tests. Bugs that only appear on a date are easy to miss in review and easy to catch in a test.

Twelve years sounds like plenty of time. Y2K once looked far away too.

## Sources

1. [The Open Group, POSIX.1-2024: 4.19 Seconds Since the Epoch](https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap04.html)
2. [Python documentation: time — Time access and conversions](https://docs.python.org/3/library/time.html)
3. [MySQL 8.4 Reference Manual: The DATE, DATETIME, and TIMESTAMP Types](https://dev.mysql.com/doc/refman/8.4/en/datetime.html)
4. [Phoronix: Linux 5.6 Is The First Kernel For 32-Bit Systems Ready To Run Past Year 2038](https://www.phoronix.com/news/Linux-5.6-32-bit-Past-Y2038)
5. [LWN.net: Debian looks forward to 2038](https://lwn.net/Articles/938149/)

## Go deeper

- https://erroneo.us/developers/famous-software-bugs/

---
Source page: https://erroneo.us/daily/year-2038-problem/ · More: https://erroneo.us/llms.txt
