Unix timestamp 2147483647 overflows the signed 32-bit integer on January 19, 2038 at 03:14:07 UTC. Covers affected systems and how 64-bit time_t fixes it.
2147483647 is 2^31 − 1, the maximum value of a signed 32-bit integer. In binary:
01111111 11111111 11111111 11111111
The leading 0 is the sign bit. When Unix timestamps were designed in the late 1960s, storing time as a 32-bit integer was a pragmatic choice that balanced precision, storage cost, and the available range. A signed 32-bit integer gives you roughly 68 years of positive timestamps starting from January 1, 1970. That was enough headroom for the foreseeable future in 1969.
That future is now January 19, 2038 at 03:14:07 UTC.
One second after 2147483647, a signed 32-bit counter rolls over:
01111111 11111111 11111111 11111111 (2147483647)
+1
10000000 00000000 00000000 00000000 (-2147483648 in two's complement)
The bit pattern 0x80000000, interpreted as a signed integer, is -2147483648. As a Unix timestamp, that corresponds to December 13, 1901 at 20:45:52 UTC. Any system that stores, compares, or displays timestamps using a signed 32-bit integer will experience one of:
Y2K (Year 2000 Problem) was caused by two digit year representations (99 → 00). It was widespread because almost every piece of software written before the late 1990s used this format, and the failure mode was silent data corruption (the year 2000 might be interpreted as 1900).
Y2K38 is structurally similar but more contained:
One difference worth noting: some embedded systems use unsigned 32-bit integers for timestamps, which extends the range to 2^32 − 1 = 4294967295, corresponding to February 7, 2106. That buys significantly more time, but those systems will eventually face the same problem.
Many microcontrollers (ARM Cortex-M, MIPS, older AVR derivatives) run on 32-bit architectures with fixed firmware. Industrial PLCs, medical devices, telecommunications equipment, and smart meters may have no viable firmware update path.
MySQL’s TIMESTAMP data type is stored internally as a 32-bit Unix timestamp and has a maximum value of 2038-01-19 03:14:07. The DATETIME type does not have this limitation. Any application using TIMESTAMP columns needs to migrate to DATETIME or BIGINT before 2038.
-- MySQL TIMESTAMP max value
SELECT FROM_UNIXTIME(2147483647);
-- Returns: 2038-01-19 03:14:07
-- DATETIME has no such limit (supports up to 9999)
ALTER TABLE events MODIFY created_at DATETIME(3);
Older 32-bit Linux systems using glibc before 2.32 use a 32-bit time_t. Distributions like Debian have patched this, but unpatched systems or custom builds may still be affected.
Executables compiled for 32-bit targets and never recompiled carry the 32-bit time_t assumption even if they run on 64-bit hardware. This includes some PHP extensions, older Python C extensions, and legacy C applications.
A 64-bit signed integer can represent timestamps up to approximately ±9.2 × 10^18 seconds from the epoch, roughly 292 billion years in either direction. In practice, the fix is to change time_t from int32_t to int64_t:
// Old (32-bit, overflows 2038)
typedef int32_t time_t;
// New (64-bit, safe for 292 billion years)
typedef int64_t time_t;
Most modern languages and runtimes already use 64-bit timestamps:
time.time() returns a float; datetime uses 64-bit internally. No Y2K38 issue.Date.now() returns milliseconds as a float64, good until the year 275760.System.currentTimeMillis() is a long (64-bit). java.time.Instant is effectively unbounded.time.Time uses a 64-bit int internally. No issue.std::time::SystemTime uses 64-bit. No issue.time_t is 64-bit. On 32-bit targets, it depends on the libc version.If you have TIMESTAMP columns in MySQL, audit whether the values need to represent dates past 2038. Migrate to DATETIME or store as BIGINT (Unix milliseconds) if so.
If you store timestamps as integers in code, make sure they are int64 / long / bigint, not int32 / int.
Add a test that creates a timestamp for January 20, 2038 and verifies your system handles it correctly. This is cheap to do now and catches the problem before it matters.
import datetime
# This should work on any modern system
future = datetime.datetime(2038, 1, 20, tzinfo=datetime.timezone.utc)
print(future.timestamp()) # Should print ~2147569200, not raise an error
If your organization runs embedded devices with fixed 32-bit firmware, document which ones are affected and their expected end of life. You have until 2038 to plan replacements, but planning late means choosing between a rushed migration and a production outage.
Nothing you paste leaves this tab. Every tool runs entirely in your browser — no upload, no server, no account.