The Leap Day Meltdown — Python Bug Hunt

Inspired by the GitHub and Azure outages that both landed on February 29th.

  • Language: Python
  • Layer: Backend
  • Difficulty: Medium
  • Concepts: Dates, Leap Years
  • Modelled on: GitHub · 2012
  • Visible tests: leap-year February clamps to the 29th; non-leap February clamps to the 28th; 31st clamps into 30-day months
  • Reward: 50 XP for a complete fix

Briefing

Inspired by the GitHub and Azure outages that both landed on February 29th. Monthly billing anniversaries get pushed "one month forward" — and every date library shortcut breaks on leap years.

billing.py computes the next billing date. Its month table thinks February always has 28 days, and it never clamps.

Bug report

BUG-0229 · Priority: High · Reported by: billing on-call

next_billing_date(year, month, day) -> [year, month, day] rules:

  • move one month forward, clamping the day to the target month's length
  • February has 29 days in leap years (divisible by 4, except centuries unless divisible by 400)

Observed: Jan 31, 2024 -> "Feb 31" -> exception; Jan 31, 2023 -> Mar 3 drift.

Logs

[billing] anniversary(2024, 1, 31) raised: day is out of range for month

The code as shipped

src/billing.py (editable)

# Computes the next monthly billing anniversary.

DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

def next_billing_date(year, month, day):
    month = month + 1
    if month > 12:
        month = 1
        year = year + 1
    return [year, month, day]

Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More Python bug hunts.