Every calendar failure in computing - Y2K in 2000, the Exchange outage of 2022, the coming 2038 rollover - has the same cause. Dates are not the problem. Representations are: fixed-width encodings that made sense when someone chose them and became wrong decades later. This article follows those encodings from their origins through their failures, because the pattern matters more than the dates. Y2K is the most punctual bug in software history. It arrived exactly when its name promised. It also frames the site’s own time problems: Days Between Dates drills the leap rule that Y2K’s programmers got wrong in both directions, and Minimum Platforms makes you confront what midnight does to arithmetic.
The anatomy of a date bug
Every date bug uses one of four mechanisms. A field-width wrap occurs
when a counter exceeds its width: “00” sorts before “99” in two-digit-year
systems, or a version stamp of 2,201,010,001 exceeds the signed 32-bit
maximum of 2,147,483,647. A sentinel collision occurs when real data
becomes indistinguishable from a reserved magic value: “99” means “never
expires,” and “00” means “unknown year,” until the rollover turns them into
live dates. A leap-rule error mishandles 29 February or day 366. The
Zune froze on 31 December 2008 in a while (days > 365) loop, and the Azure
certificate produced the nonexistent 29 February 2013. An epoch-window
misalignment occurs when a small counter is read with the wrong assumption
about where its cycle began. GPS broadcasts its week number in ten bits, so
the count wraps every 1,024 weeks. Receivers that anchor the window to
their own build date roll over on private schedules. That is why car clocks
can jump to 2002 in 2022.
The cause is always the same, and it is economic. Two-digit years were not sloppiness. In the 1960s, core memory cost about 60 cents per bit - roughly 24 dollars per byte in today’s money - and an 80-column punched card made every saved digit count. The practice was then codified: the U.S. National Bureau of Standards proposed a four-digit year in its 1968 federal standard, but other agencies - the Pentagon above all - insisted on two digits to save memory and keypunch time. The constraint disappeared. Memory became cheap, and the year 2000 arrived. The representation stayed in invisible infrastructure. The encoding is not the bug. The bug appears when real data crosses its boundary.
Y2K: the largest remediation project in history
The canonical case began with a data-representation decision in the 1960s and ended with the biggest coordinated software-maintenance effort ever mounted, at a cost estimated between 300 and 600 billion dollars worldwide. Six-digit dates appeared in the 1961 COBOL specifications, then were “enshrined as standard bureaucratic practice” when the National Bureau of Standards published FIPS PUB 4 in 1968. The format survived because nobody expected 1960s code to last for decades, and because teams copied formats forward as standards while data moved from cards to tape to disk.
The failure modes form a taxonomy, catalogued clearly in IBM’s own remediation guide. Arithmetic wrap: a person born in 1961 is 39 on 10 November 2000, but with years stored as 61 and 00 the program computes 00 - 61 = -61 - and, not expecting a signed result, ignores the sign and reports 61, “still incorrect, and even less detectable.” Sort inversion: collation logic assumes lexical order matches chronological order, so “the year 2000 (if represented as 00) will be ordered prior to the year 1999 (if represented as 99).” Every “most recent record” query inverts at the rollover. Sentinel collisions: IBM’s guide lists “99, 9/9/99, 365/99” as common encodings of “no expiration date” and “00” as “unknown year”. Decades of convention had assigned magic values to exactly the digits the rollover would produce. And leap-year confusion: the Gregorian rule has three clauses - divisible by 4, except by 100, except by 400 - and 2000 satisfies the final exception. Programmers failed in both directions: some, knowing the 100 rule but not the 400 exception, suppressed 29 February 2000; others handled it correctly by accident. The site’s Days Between Dates problem exists so you meet that three-clause rule by getting it right, not by luck.
The warnings arrived decades early. Bob Bemer - COBOL co-developer and “Father of ASCII” - noticed in 1958 and was publishing by 1971; his 1979 article is explicit: “Don’t drop the first two digits for computer processing, unless you take extreme care… Otherwise the program may fail from ambiguity in the year 2000.” The industry woke up with Peter de Jager’s 1993 article - “We are heading toward a failure of our standard date format: MM/DD/YY” - and got its name in June 1995, when programmer David Eddy’s e-mail coined “Y2K”: “it just came off my fingertips.”
The remediation economics are strange. The federal government’s own estimate rose from 4.7 billion dollars in February 1998 to 8.38 billion by December 1999. The organization overseeing the effort kept underestimating its scope. Two code-level strategies dominated. Date expansion - widening every field to four digits - was the permanent fix, but every interfacing system had to change together. Windowing left the data alone and added interpretation logic: a year below a pivot reads as 20xx, and a year at or above it reads as 19xx. It was cheaper. The warning was explicit: “dates will once again become a problem as the calendar nears the end of the window.” Hold that thought - it will be back.
At midnight on 1 January 2000, no aircraft fell and no grid collapsed. The documented failures are real, though, and they cluster in systems that had not been remediated: the NRO’s spy-satellite ground processing failed at midnight GMT (officially two to three hours, with reporting suggesting nearly three days of degraded imagery); a nuclear plant in Japan raised a detector alarm for ten minutes; roughly 150 slot machines failed at three Delaware racetracks; and CyberCash’s credit-card processing double-billed for days. CyberCash is the most instructive case. Its root cause was not the classic 00-means-1900 wrap but a date-derived file-naming collision - date logic fails at interfaces and naming schemes, not only in arithmetic. (Even the US Naval Observatory’s website displayed “Jan. 1, 19100.”)
The retrospective verdict remains unsettled. The remediation camp has the Senate’s report - Y2K Aftermath - Crisis Averted - and Koskinen’s testimony that he knew of “not a single person working on Y2K who thinks that they did not confront and avoid a major risk of systemic failure.” The skeptic camp has a control group: Italy, Russia, and South Korea spent almost nothing and had no more problems than the countries that spent billions. Both camps agree on the important points: the bug was real, the apocalyptic scenarios were never technically plausible, and the quiet New Year proves nothing by itself.
Y2K22: the same bug, twenty-two years later
On 1 January 2022, on-premises Microsoft Exchange servers worldwide stopped
delivering mail. The failing component was the anti-malware scan engine.
The error message was the smoking gun: Event 5300, “Can’t convert
‘2201010001’ to long.” The engine’s version stamp was a ten-digit encoding
of its build time in YYMMDDHHMM form, parsed as a signed 32-bit integer -
and 2,201,010,001 exceeds the 32-bit maximum of 2,147,483,647 by about 53
million. The smallest possible 2022 stamp was already unrepresentable. This
was not a bad update; it was a permanent property of the numbering scheme.
Microsoft never confirmed the mechanism, describing only “a date check
failure.” Administrator Joseph Roosen reverse-engineered the int32 diagnosis
the same day, and the error string, the shape of the fix, and the arithmetic
strongly support it.
The fix repeats the Y2K lesson in miniature. Microsoft shipped a script that reset the engine and forced it to report version 2112330001 - which, read as YYMMDDHHMM, decodes to 33 December 2021, a date that does not exist. It was larger than every genuine December 2021 stamp while staying under the int32 ceiling. Microsoft did not widen the field. The remediation replanted the same bounded representation behind a fake pivot - windowing, replayed. A durable fix arrived only with the March 2022 security update. (SonicWall’s email security products failed the same day from the same class of bug, in an independent codebase: the ten-digit stamp in a signed int32 was an industry pattern, not one team’s mistake.)
The same week supplied a stranger example from the same bug family. Navigation clocks in 2004-2012 Honda and Acura vehicles rolled back to May 2002 - exactly 1,024 weeks earlier, which is 2^10 weeks: a GPS week-number rollover. It was Honda’s third such failure (2017, 2021, 2022), and owners found the smoking gun in diagnostic menus showing the GPS date reading 19-21 May 2002. Honda never explained the bug. The press therefore imported the Exchange int32 explanation, even though that theory cannot explain a date exactly 1,024 weeks in the past or the self-correction Honda correctly predicted. Two incidents with entirely different mechanisms became one folk diagnosis: “computers can’t handle 2022.” When vendors stay silent, the loudest available explanation fills the vacuum.
The year 2038: the one still coming
The rollover that exceeds everything catalogued above is the signed 32-bit
Unix time_t. It arrives at 03:14:07 UTC on 19 January 2038 - 2,147,483,647
seconds after the 1970 epoch - and the counter then wraps to 1901. The fix
is not a mystery. The installed base is the problem. The first documented
victim failed 32 years early: in May 2006, AOLserver used a timeout of
10^9 seconds (about 31.7 years) to mean “never.” Once current time plus 10^9
seconds exceeded the int32 maximum, computed expiries landed in the past and
connections closed instantly. Any program that computes a date N years in
the future hits the boundary N years early. Thirty-year mortgages,
long-lived certificates, and multi-decade embedded deployments pull failures
forward by exactly their horizon. That is why 32-bit systems were already
hitting EOVERFLOW on post-2038 filesystem timestamps in 2025.
The industry’s strategy is attrition, not repair. NetBSD moved to 64-bit
time in 2012; OpenBSD in 2014; musl switched in 2020; Debian’s 13th release
rebuilt with 64-bit time while deliberately excluding 32-bit i386; and
POSIX.1-2024 now requires time_t to be at least 64 bits. Linux added 64-bit
time64 syscalls in 2019, but glibc’s support remains opt-in. The exposure
that matters is the embedded long tail - cars, industrial controllers,
medical devices - where lifespans run 20 to 30 years, no update path exists,
and hardware replacement is the fix. It is the same class that made Y2K
expensive, minus the remediation budget this time. Even the date has a
predecessor: the NTP era rollover - unsigned 32-bit seconds since 1900 -
arrives on 7 February 2036, almost two years before the famous one.
What the pattern teaches
Four lessons came from four decades. First, representations outlive their economics: a two-digit year was rational at 60 cents per bit and irrational at a fraction of a cent, and nothing in the code noticed the difference. When you design a field, audit its width against its lifetime, not against today’s data. Second, cheap fixes replant the bug: windowing deferred ambiguity, Exchange’s fake “Dec 33” stamp deferred the int32 ceiling, unsigned time_t merely moves 2038 to 2106 - every deferral is a ticking clock that inherits the original design’s assumptions. Third, failures arrive early: the rollover date is the last failure, not the first, because anything that computes a future date crosses the boundary years ahead of schedule. Fourth, language design is prevention: the two languages this site teaches took opposite paths, and the next article in this series - time and monotonicity: JavaScript vs. Elixir - is about what each model does to the failure class this article just catalogued. The bugs are not really about dates. They are about counting things in fixed widths and assuming the width will outlive the thing being counted.
Where to go next
-
Days Between Dates and Friday the 13ths
- the leap rule Y2K’s programmers got wrong, drilled until you get it right.
- Minimum Platforms - the site’s HARD time problem, where midnight wraps around and naive arithmetic breaks.
- What O(n) actually promises - the notation behind “32-bit is 2,147,483,647” and why widths are ceilings.
-
Time and monotonicity: JavaScript vs. Elixir
- what the two languages this site teaches do differently about all of the above.
-
Real numbers, and the lies programming languages tell about them
- the arithmetic underneath every width: why “two digits for the year” is a floating-point problem in disguise.
- Bits have no meaning - the closing line’s deeper form: representations outlive their economics because the bits never carried meaning in the first place.