Computers have counted seconds since 1970: the 2038 problem and the end of the leap second
· Science, Technology
Type date +%s in a terminal and you get a single number. While I was preparing this post it printed 1,792,761,102. That is the count of seconds since the start of 1 January 1970. File dates, cookie lifetimes, log entries and certificates are stored this way in a lot of places: time as one whole number. Two dates stand out in the story of that number right now. On 19 January 2038, 32-bit counters run out, and from 20 May 2027 the world's clock stops adding leap seconds. The two are often mixed up, yet they are not the same problem.
If the topic is new to you, the simplest way to picture it is a car odometer. It rolls from 999,999 to 000,000 because it has only six digits. A computer's second counter also has a limited number of digits. When they run out, the counter wraps around and the clock shows the wrong time. Below I go step by step and explain the technical terms.
- Unix time is the number of seconds since 00:00:00 UTC on 1 January 1970.
- A signed 32-bit counter fills up at 03:14:07 UTC on 19 January 2038. A 64-bit counter removes the problem in practice.
- Unix time does not count leap seconds. Under the October 2026 decision, UTC will stop adding them from 20 May 2027.
- One concerns how many bits a number has, the other how the clock is defined. Neither fixes the other.
- 🔢 Bit The smallest unit of information in a computer: a switch that is on or off. Numbers are written with rows of these switches. 32 bits means 32 switches.
- ➕ Signed number A number that can hold both negative and positive values. One switch is reserved for the sign, so the ceiling is halved.
- 🌍 UTC The time standard used worldwide. Time zones are calculated from it.
- ➰ Leap second An extra second occasionally added to UTC to close the gap between atomic clocks and the Earth's rotation.
- 📟 Embedded system A small computer dedicated to one job, such as a router, a camera or a vehicle control unit.
How did a number become a calendar?
By the POSIX definition, Unix time gives the seconds elapsed since the "Epoch" and counts every day as exactly 86,400 seconds (Open Group, section 4.16). The Epoch is 00:00:00 UTC on 1 January 1970. The date has no special meaning. Wikipedia reports that Unix engineers picked it because it was a convenient date to work with. Early versions were different: the system used a 32-bit counter ticking 60 times per second, which could cover about two years and three months. To avoid the overflow the start date was moved, 1971 and 1972 were both tried, and finally counting switched to whole seconds.
$ date +%s # current time in seconds
$ date -u -d @0 # GNU date: number to date
Thu Jan 1 00:00:00 UTC 1970
$ date -u -d @-2147483648 # negative number, before 1970
Fri Dec 13 20:45:52 UTC 1901The first command prints the current time in seconds. The second turns a number of seconds into a readable date: 0 is the first moment of 1970. The third goes back before 1970 when given a negative number. On macOS and BSD systems, use -r number instead of -d @number. I ran these commands on my own machine to check the output.

On machines of that era, "number" was a far more physical thing than it is today. The panel shows rows of lights for the address and data lines, and the width of a number was the length of a row. To my mind that is a good way into the 2038 problem. The wider you make the counter, the further it counts, and at some point the row ends.
What overflows in 2038?
If you store Unix time in a signed 32-bit integer, the ceiling is 2³¹ − 1, or 2,147,483,647. That number corresponds to 03:14:07 UTC on 19 January 2038. One second later the counter wraps to its smallest value, −2³¹, and a program reading it as a date sees 20:45:52 UTC on 13 December 1901 (Wikipedia). Back to the odometer: 2,147,483,647 is this counter's "999,999", and the next step is the wrap. "Signed" means one of the 32 switches is set aside for "negative or positive". That leaves 31, which is where the 2³¹ − 1 ceiling comes from. The same behaviour fits in a few lines:
import struct, datetime
t = 2**31 # 03:14:08 UTC, 19 January 2038
wrapped = struct.unpack('<i', struct.pack('<I', t))[0]
print(wrapped) # -2147483648
print(datetime.datetime.fromtimestamp(wrapped, datetime.timezone.utc))
# 1901-12-13 20:45:52+00:00The code tries to fit 2³¹ into a signed counter with 32 switches. It does not fit, the counter wraps to its smallest value, and the date lands in 1901. The diagram below shows the same thing visually.

- 2,147,483,647 ceiling of a signed 32-bit counter (19 January 2038 03:14:07 UTC)
- ≈ 11 years 3 months time left until 2038 (as of 23 October 2026)
- 7 February 2106 next ceiling if the same counter were unsigned (06:28:15 UTC)
- ≈ 292 billion years ceiling of a signed 64-bit counter (Wikipedia)
Where is the risk, and where is it not?
The short answer: most of our everyday devices are fine. Most phones and laptops already use 64-bit time, meaning a counter with 64 switches instead of 32. The harder cases are long-lived 32-bit embedded systems: routers, cameras, vehicle control units. According to Wikipedia's overview, these devices are at risk when they compute dates or write logs, and they can be hard or impossible to update. Systems that only measure the difference between two moments are not expected to have a serious problem.
There is no need to wait for 2038 either. In 2006, AOLserver hit the overflow on 13 May, after 01:27:28 UTC, because of a timeout set one billion seconds into the future. Lowering the setting fixed it. The same source says certificates with an expiry date past 2038 can fail verification on 32-bit systems. My takeaway: any code that computes a value in the future (a certificate, a cookie, a subscription period) can hit the limit well before 2038 arrives.
The fix: widen the counter
The core of the fix is simple: make the counter 64 bits. Most 64-bit systems already do. In the timeline Wikipedia lists, the Linux kernel can use a 64-bit time_t on 32-bit architectures from 5.6 (2020), and glibc enables it since 2.34 (August 2021) when _TIME_BITS=64 is defined. A Gnulib discussion notes that on 32-bit targets _FILE_OFFSET_BITS=64 should be given as well. In your own code you can check this:
#include <stdio.h>
#include <time.h>
int main(void) {
printf("time_t: %zu bytes\n", sizeof(time_t));
return 0;
}$ gcc -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 t.c -o t
$ ./t
time_t: 8 bytesOn my 64-bit machine the program prints 8 bytes even without the flags. Compiled without them for a 32-bit target, it will often print 4, and that is where the trouble starts. time_t is the name of the C data type that holds time. Time does not live only there: file systems, database columns and network protocols carry their own fields. The table below puts these limits side by side.
| System or type | Limit | Note |
|---|---|---|
| Signed 32-bit time_t | 19 January 2038 | Older 32-bit systems |
| Unsigned 32-bit time_t | 7 February 2106 | Breaks dates before 1970 |
| ext4 (inodes larger than 128 bytes) | 2446 | Extended with extra bits |
| XFS big timestamps | 2486 | Since Linux 5.10 |
| Signed 64-bit time_t | ≈ 292 billion years | Default on most 64-bit systems |
The counter never counted leap seconds
The Earth's rotation is not perfectly regular at the precision of atomic clocks. UTC follows atomic clocks, UT1 follows the Earth's rotation, and when the gap approached 0.9 seconds a leap second was added to UTC. Unix time counts every day as 86,400 seconds, while UTC occasionally has days of 86,401. When a leap second is inserted, the Unix number repeats itself: 1483228800 can mean either 23:59:60 on 31 December 2016 or 00:00:00 on 1 January 2017. The difference between two timestamps that span a leap second also comes out one second short (Wikipedia).
$ date -u -d @1483228800
Sun Jan 1 00:00:00 UTC 2017 # GNU date never shows the ":60" momentThat picture is changing. In 2022 the General Conference on Weights and Measures (CGPM) decided that the maximum UT1 − UTC difference would be increased "in, or before, 2035" (Resolution 4). The 28th CGPM, which met on 13-15 October 2026, brought it forward. Resolution 5 says continuous UTC becomes effective on 20 May 2027 and the maximum |UT1 − UTC| will be 3,600 seconds (1 hour). The recitals also say that a "negative leap second", never applied so far, is considered high risk. Euronews covered the news as well.
- 1970 Epoch — Unix time counts from 00:00:00 UTC on 1 January 1970
- 2006 AOLserver overflow — A timeout of one billion seconds crossed the limit early
- Aug 2021 glibc 2.34 — 64-bit time_t option on 32-bit platforms
- 2022 CGPM Resolution 4 — Aim to relax the leap-second limit in or before 2035
- 15 Oct 2026 CGPM Resolution 5 — Continuous UTC decided, difference limit 3,600 seconds
- 20 May 2027 Continuous UTC — Leap seconds stop being added
- 19 Jan 2038 32-bit limit — Signed 32-bit counter fills at 03:14:07 UTC
Why do the two get mixed up?
In my view the confusion comes from both carrying a "time" label. 2038 is a storage problem: how many bits is the number? The leap second is about the definition of the clock: how many seconds are in a day? A system that moves to 64 bits still does not count leap seconds, and a world that drops leap seconds does not widen a 32-bit counter. There is a small irony too. Unix time was designed by ignoring leap seconds, and once UTC stops adding them, that omission will create no new ambiguity after 2027. That is my inference, not something the resolution says. The practical upshot for an ordinary user: you will not see any change on your phone's clock. The seconds already added stay in history, and so does the ambiguity in older records.
In your own project If you keep a timestamp in a 32-bit field in a database or a file format, records dated in the future (subscriptions, certificates, cookie lifetimes) can cause trouble long before 2038. Checking the field width once may be enough.
Will my phone or computer break in 2038?
Modern 64-bit operating systems generally use 64-bit time. The real risk is in older 32-bit devices that are never updated and in data formats with 32-bit fields. For a specific device, check the manufacturer's statement.
Would an unsigned counter solve it?
It postpones the limit to 7 February 2106, but it breaks dates before 1970, since those are represented as negative numbers.
Will ending the leap second shift clocks by an hour?
No. The decision allows the gap between UT1 and UTC to grow up to 3,600 seconds. The resolution says this ensures continuity for several centuries.
If you are interested in the history of code and computers, you may also like this post (in Turkish):
İlk bilgisayarlar bugünkü kodu anlar mıydı? Kodlamanın kısa tarihi — A short history from ENIAC's wires to stored programs and today's languages.
Sources
- Unix time, Wikipedia (accessed: 2026-10-23)
- Year 2038 problem, Wikipedia (accessed: 2026-10-23)
- The Open Group Base Specifications, 4.16 Seconds Since the Epoch (accessed: 2026-10-23)
- PDP-11, Wikipedia (accessed: 2026-10-23)
- BIPM, 28th CGPM (2026), Resolution 5: On the technical actions needed to ensure the continuity of UTC (accessed: 2026-10-23)
- BIPM, 27th CGPM (2022), Resolution 4 (accessed: 2026-10-23)
- Euronews, 16 October 2026: global timekeeping rules change, leap second scrapped from 2027 (accessed: 2026-10-23)
- Gnulib: discussion of glibc 2.34 _TIME_BITS=64 support (accessed: 2026-10-23)
Cover image: Jason Scott · CC BY 2.0. Diagram: original graphic.