Ask HN: Did you encounter any leap year bugs today?
Leap day 2024 exposed a surprising number of software and hardware failures, from broken payment systems, access control locks, games, and watches to unit tests, billing systems, and even large language models rejecting February 29 as invalid. Contributors trace many of these errors to naive date arithmetic (like “subtract one year”), custom time handling, and edge cases such as rolling anniversaries, certificates, and retention windows that weren’t tested across leap years. The incidents reinforce long‑standing advice to rely on mature date/time libraries, design clearer business rules around time, and explicitly test rare calendar cases rather than assuming they will “just work.”
Real-world outages and operational issues
- Multiple payment systems failed:
- Major Swedish grocery chain and New Zealand self-service fuel pumps couldn’t process card payments, forcing cash or app-based workarounds.
- Some credit-card and invoicing systems mis-scheduled due dates or notifications when encountering Feb 29.
- Physical-world systems glitched:
- Hotel keycards stopped working, requiring special hardware resets; similar issue cited from 2020.
- Streetlights in Paris and at least one campus stayed off at night, likely due to date-based control.
- Access-control cameras and some solar/energy monitoring systems blocked entry or stopped logging data.
- Consumer services and games:
- Several EA titles and specific games (e.g., racing and rhythm titles) crashed or locked players out until system clocks were moved to March 1.
- Airlines and transport apps printed wrong dates or mis-labeled schedules, sometimes with banner disclaimers as a workaround.
- Cloudflare billing produced invoices dated “1970-01-01” alongside a wider billing incident.
Programming pitfalls with leap years
- Many bugs came from naïve “add/subtract a year” logic:
- Code using
replace(year=year±1)or assuming 365 days threw errors or produced wrong dates (e.g., 1894‑02‑29 in DB2). - Rolling-year and YTD calculations failed because there is no Feb 29 in the comparison year.
- Unit tests that depend on “today” or assume fixed year lengths broke in CI.
- Code using
- Python, Java, and others were discussed:
- Standard
timedelta/Durationonly support days/seconds; “years” are ambiguous. - Libraries like dateutil’s
relativedelta, Arrow, Carbon, date-fns, and .NET’sAddYearswere cited as safer options, but edge cases still require explicit decisions.
- Standard
- Debate on definition:
- “Subtract a year” can mean 365/365.25 days, same calendar date, or same “semantic” date (e.g., last Monday in January).
- Several argue any behavior is acceptable as long as it’s consistent and doesn’t crash; others emphasize legal and business rules usually expect “12 calendar months.”
User experience oddities and birthdays
- Many watches, apps, and forms simply skipped Feb 29, showed March 1, or disallowed 29 as a valid February date; some devices intentionally hard-code February to 28 days.
- Leap-day birthdays exposed edge cases:
- Systems variously map them to Feb 28 or Mar 1 for age checks, licenses, and legal thresholds, sometimes incorrectly blocking actions.
- People report forms missing Feb 29, or frontends accepting it but saving as Feb 28.
LLMs and meta-lessons
- Several reports that ChatGPT and other LLMs:
- Initially claimed 2024 isn’t a leap year or rejected 2024‑02‑29 as invalid, then self-corrected mid-explanation.
- Struggle with tokenization-related tasks (e.g., counting letters in a word).
- Some see this as proof LLMs shouldn’t back critical logic; others argue they’re fine for non-critical, human-in-the-loop workflows if sandboxed.
- Broad consensus: time handling is deceptively hard; don’t roll your own date logic or ignore Feb 29/century rules, and make tests explicitly cover these edge cases.