FAILURE MAP
← Case archive

FA-77116 / Calendar recurrence rules / Open access

Yearly ISO BYWEEKNO/BYDAY expansion: week count · case 01

BYWEEKNO=-1 is resolved to week 0 in years whose December 31 belongs to next year's week 1.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The week count is read from December 31, which may lie in the next ISO year.

VERIFIED REPAIR

At the week count decision use `dt.date(y, 12, 28).isocalendar()[1]`, leaving the other decision sites of the model unchanged.

Unsuccessful approach: The partial repair `53 if dt.date(y, 1, 1).weekday() == 3 else 52` misses leap years that begin on Wednesday, which also have 53 weeks.

Case contract

FREQ=YEARLY with BYWEEKNO (ISO weeks, Monday start, week 1 contains January 4) and BYDAY weekdays (0=Monday). Negative week numbers count from the last ISO week of the year (-1 is the last). A year has 53 weeks exactly when December 28 falls in week 53; week numbers outside 1..weeks are ignored for that year. Dates may fall in the adjacent calendar year. Expand years year_start .. year_start+years-1 and return unique ISO dates sorted.

Why this case matters

Recurring calendar series are expanded into concrete instances for display, reminders and conflict checks.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import datetime as dt
import calendar
N = 1
observations = []
def solve(year_start, weeknos, weekdays, years):
    out = set()
    for y in range(year_start, year_start + years):
        jan4 = dt.date(y, 1, 4)
        week1 = jan4 - dt.timedelta(days=jan4.weekday())
        nweeks = dt.date(y, 12, 31).isocalendar()[1]
        for wn in weeknos:
            w = wn if wn > 0 else nweeks + wn + 1
            if not (1 <= w <= nweeks):
                continue
            for wd in weekdays:
                out.add(week1 + dt.timedelta(days=(w - 1) * 7 + wd))
    return sorted(d.isoformat() for d in out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: week 1 in 2021', [2021, [1], [0], 1], ['2021-01-04']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28']),
  ('last week negative', [2020, [-1], [6], 3], ['2021-01-03', '2022-01-02', '2023-01-01']),
  ('leap year starting wednesday', [2024, [-1, 53], [0], 2], ['2024-12-23', '2025-12-22']),
  ('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']),
  ('too-negative week', [2021, [-60, 2], [2], 1], ['2021-01-13']),
  ('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01'])],
 [('last week negative', [2020, [-1], [6], 3], ['2021-01-03', '2022-01-02', '2023-01-01']),
  ('leap year starting wednesday', [2024, [-1, 53], [0], 2], ['2024-12-23', '2025-12-22']),
  ('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']),
  ('too-negative week', [2021, [-60, 2], [2], 1], ['2021-01-13']),
  ('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']),
  ('second to last week', [2026, [-2], [3], 2], ['2026-12-24', '2027-12-23']),
  ('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27'])],
 [('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']),
  ('too-negative week', [2021, [-60, 2], [2], 1], ['2021-01-13']),
  ('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']),
  ('second to last week', [2026, [-2], [3], 2], ['2026-12-24', '2027-12-23']),
  ('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27']),
  ('year starting saturday', [2022, [1, 53], [1, 5], 1], ['2022-01-04', '2022-01-08']),
  ('53 in 2026', [2026, [53], [4], 1], ['2027-01-01']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28'])],
 [('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']),
  ('second to last week', [2026, [-2], [3], 2], ['2026-12-24', '2027-12-23']),
  ('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27']),
  ('year starting saturday', [2022, [1, 53], [1, 5], 1], ['2022-01-04', '2022-01-08']),
  ('53 in 2026', [2026, [53], [4], 1], ['2027-01-01']),
  ('regression: week 1 in 2021', [2021, [1], [0], 1], ['2021-01-04']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28']),
  ('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17'])],
 [('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27']),
  ('year starting saturday', [2022, [1, 53], [1, 5], 1], ['2022-01-04', '2022-01-08']),
  ('53 in 2026', [2026, [53], [4], 1], ['2027-01-01']),
  ('regression: week 1 in 2021', [2021, [1], [0], 1], ['2021-01-04']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28']),
  ('last week negative', [2020, [-1], [6], 3], ['2021-01-03', '2022-01-02', '2023-01-01']),
  ('leap year starting wednesday', [2024, [-1, 53], [0], 2], ['2024-12-23', '2025-12-22'])]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: week 1 in 2021['2021-01-04']['2021-01-04']Passed
week 53 existence['2020-12-28']['2020-12-28']Passed
last week negative['2021-01-03', '2022-01-02', '2023-01-01']['2021-01-03', '2022-01-02', '2023-01-01']Passed
leap year starting wednesday['2024-01-01', '2024-12-30']['2024-12-23', '2025-12-22']Failed
week 20 monday friday['2023-05-15', '2023-05-19']['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']Failed
too-negative week['2021-01-13']['2021-01-13']Passed
week 1 sunday spans years['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']Passed

SHA-256 / 42fa55744261b19d187a48c585a369dc96497a8a9146baf15b0141a659e24069

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import datetime as dt
import calendar
N = 1
observations = []
def solve(year_start, weeknos, weekdays, years):
    out = set()
    for y in range(year_start, year_start + years):
        jan4 = dt.date(y, 1, 4)
        week1 = jan4 - dt.timedelta(days=jan4.weekday())
        nweeks = 53 if dt.date(y, 1, 1).weekday() == 3 else 52
        for wn in weeknos:
            w = wn if wn > 0 else nweeks + wn + 1
            if not (1 <= w <= nweeks):
                continue
            for wd in weekdays:
                out.add(week1 + dt.timedelta(days=(w - 1) * 7 + wd))
    return sorted(d.isoformat() for d in out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: week 1 in 2021', [2021, [1], [0], 1], ['2021-01-04']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28']),
  ('last week negative', [2020, [-1], [6], 3], ['2021-01-03', '2022-01-02', '2023-01-01']),
  ('leap year starting wednesday', [2024, [-1, 53], [0], 2], ['2024-12-23', '2025-12-22']),
  ('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']),
  ('too-negative week', [2021, [-60, 2], [2], 1], ['2021-01-13']),
  ('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01'])],
 [('last week negative', [2020, [-1], [6], 3], ['2021-01-03', '2022-01-02', '2023-01-01']),
  ('leap year starting wednesday', [2024, [-1, 53], [0], 2], ['2024-12-23', '2025-12-22']),
  ('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']),
  ('too-negative week', [2021, [-60, 2], [2], 1], ['2021-01-13']),
  ('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']),
  ('second to last week', [2026, [-2], [3], 2], ['2026-12-24', '2027-12-23']),
  ('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27'])],
 [('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']),
  ('too-negative week', [2021, [-60, 2], [2], 1], ['2021-01-13']),
  ('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']),
  ('second to last week', [2026, [-2], [3], 2], ['2026-12-24', '2027-12-23']),
  ('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27']),
  ('year starting saturday', [2022, [1, 53], [1, 5], 1], ['2022-01-04', '2022-01-08']),
  ('53 in 2026', [2026, [53], [4], 1], ['2027-01-01']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28'])],
 [('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']),
  ('second to last week', [2026, [-2], [3], 2], ['2026-12-24', '2027-12-23']),
  ('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27']),
  ('year starting saturday', [2022, [1, 53], [1, 5], 1], ['2022-01-04', '2022-01-08']),
  ('53 in 2026', [2026, [53], [4], 1], ['2027-01-01']),
  ('regression: week 1 in 2021', [2021, [1], [0], 1], ['2021-01-04']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28']),
  ('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17'])],
 [('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27']),
  ('year starting saturday', [2022, [1, 53], [1, 5], 1], ['2022-01-04', '2022-01-08']),
  ('53 in 2026', [2026, [53], [4], 1], ['2027-01-01']),
  ('regression: week 1 in 2021', [2021, [1], [0], 1], ['2021-01-04']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28']),
  ('last week negative', [2020, [-1], [6], 3], ['2021-01-03', '2022-01-02', '2023-01-01']),
  ('leap year starting wednesday', [2024, [-1, 53], [0], 2], ['2024-12-23', '2025-12-22'])]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: week 1 in 2021['2021-01-04']['2021-01-04']Passed
week 53 existence[]['2020-12-28']Failed
last week negative['2020-12-27', '2022-01-02', '2023-01-01']['2021-01-03', '2022-01-02', '2023-01-01']Failed
leap year starting wednesday['2024-12-23', '2025-12-22']['2024-12-23', '2025-12-22']Passed
week 20 monday friday['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']Passed
too-negative week['2021-01-13']['2021-01-13']Passed
week 1 sunday spans years['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']Passed

SHA-256 / ab3de404c93d3bf980f7abe1e25efa013b5884a577654ba52eb4f44bf96f871f

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import datetime as dt
import calendar
N = 1
observations = []
def solve(year_start, weeknos, weekdays, years):
    out = set()
    for y in range(year_start, year_start + years):
        jan4 = dt.date(y, 1, 4)
        week1 = jan4 - dt.timedelta(days=jan4.weekday())
        nweeks = dt.date(y, 12, 28).isocalendar()[1]
        for wn in weeknos:
            w = wn if wn > 0 else nweeks + wn + 1
            if not (1 <= w <= nweeks):
                continue
            for wd in weekdays:
                out.add(week1 + dt.timedelta(days=(w - 1) * 7 + wd))
    return sorted(d.isoformat() for d in out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: week 1 in 2021', [2021, [1], [0], 1], ['2021-01-04']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28']),
  ('last week negative', [2020, [-1], [6], 3], ['2021-01-03', '2022-01-02', '2023-01-01']),
  ('leap year starting wednesday', [2024, [-1, 53], [0], 2], ['2024-12-23', '2025-12-22']),
  ('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']),
  ('too-negative week', [2021, [-60, 2], [2], 1], ['2021-01-13']),
  ('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01'])],
 [('last week negative', [2020, [-1], [6], 3], ['2021-01-03', '2022-01-02', '2023-01-01']),
  ('leap year starting wednesday', [2024, [-1, 53], [0], 2], ['2024-12-23', '2025-12-22']),
  ('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']),
  ('too-negative week', [2021, [-60, 2], [2], 1], ['2021-01-13']),
  ('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']),
  ('second to last week', [2026, [-2], [3], 2], ['2026-12-24', '2027-12-23']),
  ('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27'])],
 [('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']),
  ('too-negative week', [2021, [-60, 2], [2], 1], ['2021-01-13']),
  ('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']),
  ('second to last week', [2026, [-2], [3], 2], ['2026-12-24', '2027-12-23']),
  ('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27']),
  ('year starting saturday', [2022, [1, 53], [1, 5], 1], ['2022-01-04', '2022-01-08']),
  ('53 in 2026', [2026, [53], [4], 1], ['2027-01-01']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28'])],
 [('week 1 sunday spans years',
   [2015, [1, 52], [6], 2],
   ['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']),
  ('second to last week', [2026, [-2], [3], 2], ['2026-12-24', '2027-12-23']),
  ('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27']),
  ('year starting saturday', [2022, [1, 53], [1, 5], 1], ['2022-01-04', '2022-01-08']),
  ('53 in 2026', [2026, [53], [4], 1], ['2027-01-01']),
  ('regression: week 1 in 2021', [2021, [1], [0], 1], ['2021-01-04']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28']),
  ('week 20 monday friday',
   [2023, [20], [0, 4], 2],
   ['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17'])],
 [('many weeks', [2027, [1, -1, 26], [0], 1], ['2027-01-04', '2027-06-28', '2027-12-27']),
  ('year starting saturday', [2022, [1, 53], [1, 5], 1], ['2022-01-04', '2022-01-08']),
  ('53 in 2026', [2026, [53], [4], 1], ['2027-01-01']),
  ('regression: week 1 in 2021', [2021, [1], [0], 1], ['2021-01-04']),
  ('week 53 existence', [2019, [53], [0], 3], ['2020-12-28']),
  ('last week negative', [2020, [-1], [6], 3], ['2021-01-03', '2022-01-02', '2023-01-01']),
  ('leap year starting wednesday', [2024, [-1, 53], [0], 2], ['2024-12-23', '2025-12-22'])]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: week 1 in 2021['2021-01-04']['2021-01-04']Passed
week 53 existence['2020-12-28']['2020-12-28']Passed
last week negative['2021-01-03', '2022-01-02', '2023-01-01']['2021-01-03', '2022-01-02', '2023-01-01']Passed
leap year starting wednesday['2024-12-23', '2025-12-22']['2024-12-23', '2025-12-22']Passed
week 20 monday friday['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']['2023-05-15', '2023-05-19', '2024-05-13', '2024-05-17']Passed
too-negative week['2021-01-13']['2021-01-13']Passed
week 1 sunday spans years['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']['2015-01-04', '2015-12-27', '2016-01-10', '2017-01-01']Passed

SHA-256 / 5dc0de7a3b7d160f05de97be5444b7dae8c358b3664092a1e87c474c10d12d00

Verification & scope

Stipulated, bounded recurrence-expansion model evaluated offline on explicit fixtures; it is not a complete iCalendar implementation and makes no claim of standards conformance. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:49:22.544167+00:00.

Case digest / ae9449cddce92fa07c94f6a9e1a46721d29fd265503854cca18dca649af36bb8