FA-77271 / Calendar recurrence rules / Open access
Closed-form final date of a COUNT-limited weekly BYDAY series: empty count · case 01
COUNT=0 reports a final date although the series is empty.
ROOT CAUSE
Only negative counts are treated as an empty series.
VERIFIED REPAIR
At the empty count decision use `count < 1`, leaving the other decision sites of the model unchanged.
Unsuccessful approach: The partial repair `count == 0` handles zero but a negative count still yields a date.
Case contract
For FREQ=WEEKLY;INTERVAL;BYDAY;WKST;COUNT starting at dtstart (weeks begin on wkst, days of the first week before dtstart are skipped, active weeks every interval weeks from the dtstart week), compute the date of the final instance arithmetically, without expanding. count < 1 returns None. The result must equal the last element of the full expansion.
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(dtstart, interval, byday, wkst, count):
start = dt.date.fromisoformat(dtstart)
if count < 0:
return None
days = sorted(set(byday), key=lambda w: (w - wkst) % 7)
week0 = start - dt.timedelta(days=(start.weekday() - wkst) % 7)
first_week = [w for w in days if (w - wkst) % 7 >= (start.weekday() - wkst) % 7]
if count <= len(first_week):
w = first_week[count - 1]
weeks = 0
else:
rest = count - len(first_week)
weeks = (rest - 1) // len(days) + 1
w = days[(rest - 1) % len(days)]
last = week0 + dt.timedelta(days=weeks * interval * 7 + (w - wkst) % 7)
return last.isoformat()
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: WKST=SU interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 6, 4], '1997-08-31'),
('WKST=MO interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 0, 4], '1997-08-24'),
('multiple of weekday count', ['2024-01-01', 1, [0, 2, 4], 0, 6], '2024-01-12'),
('partial first week', ['2024-01-04', 1, [0, 2, 4], 0, 5], '2024-01-15'),
('interval 3 single day', ['2024-05-06', 3, [4], 0, 3], '2024-06-21'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None)],
[('multiple of weekday count', ['2024-01-01', 1, [0, 2, 4], 0, 6], '2024-01-12'),
('partial first week', ['2024-01-04', 1, [0, 2, 4], 0, 5], '2024-01-15'),
('interval 3 single day', ['2024-05-06', 3, [4], 0, 3], '2024-06-21'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None),
('within first week', ['2024-01-01', 2, [0, 1, 2], 0, 2], '2024-01-02'),
('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23')],
[('interval 3 single day', ['2024-05-06', 3, [4], 0, 3], '2024-06-21'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None),
('within first week', ['2024-01-01', 2, [0, 1, 2], 0, 2], '2024-01-02'),
('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23'),
('WKST=WE interval 2', ['2024-06-04', 2, [0, 3], 2, 7], '2024-07-25'),
('dtstart after all first-week days', ['2024-01-06', 2, [0, 1], 0, 5], '2024-02-12')],
[('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None),
('within first week', ['2024-01-01', 2, [0, 1, 2], 0, 2], '2024-01-02'),
('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23'),
('WKST=WE interval 2', ['2024-06-04', 2, [0, 3], 2, 7], '2024-07-25'),
('dtstart after all first-week days', ['2024-01-06', 2, [0, 1], 0, 5], '2024-02-12'),
('long series', ['2025-02-03', 2, [1, 3, 5], 0, 11], '2025-03-20'),
('regression: WKST=SU interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 6, 4], '1997-08-31'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None)],
[('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23'),
('WKST=WE interval 2', ['2024-06-04', 2, [0, 3], 2, 7], '2024-07-25'),
('dtstart after all first-week days', ['2024-01-06', 2, [0, 1], 0, 5], '2024-02-12'),
('long series', ['2025-02-03', 2, [1, 3, 5], 0, 11], '2025-03-20'),
('regression: WKST=SU interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 6, 4], '1997-08-31'),
('WKST=MO interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 0, 4], '1997-08-24'),
('multiple of weekday count', ['2024-01-01', 1, [0, 2, 4], 0, 6], '2024-01-12'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: WKST=SU interval 2 TU,SU | 1997-08-31 | 1997-08-31 | Passed |
| WKST=MO interval 2 TU,SU | 1997-08-24 | 1997-08-24 | Passed |
| multiple of weekday count | 2024-01-12 | 2024-01-12 | Passed |
| partial first week | 2024-01-15 | 2024-01-15 | Passed |
| interval 3 single day | 2024-06-21 | 2024-06-21 | Passed |
| count zero | 2024-01-01 | None | Failed |
| count negative | None | None | Passed |
SHA-256 / dd2e6da172ce2c0f50292aef75cdf4a4b643bceb6b952ce94b5f5419b0e15d8f
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(dtstart, interval, byday, wkst, count):
start = dt.date.fromisoformat(dtstart)
if count == 0:
return None
days = sorted(set(byday), key=lambda w: (w - wkst) % 7)
week0 = start - dt.timedelta(days=(start.weekday() - wkst) % 7)
first_week = [w for w in days if (w - wkst) % 7 >= (start.weekday() - wkst) % 7]
if count <= len(first_week):
w = first_week[count - 1]
weeks = 0
else:
rest = count - len(first_week)
weeks = (rest - 1) // len(days) + 1
w = days[(rest - 1) % len(days)]
last = week0 + dt.timedelta(days=weeks * interval * 7 + (w - wkst) % 7)
return last.isoformat()
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: WKST=SU interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 6, 4], '1997-08-31'),
('WKST=MO interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 0, 4], '1997-08-24'),
('multiple of weekday count', ['2024-01-01', 1, [0, 2, 4], 0, 6], '2024-01-12'),
('partial first week', ['2024-01-04', 1, [0, 2, 4], 0, 5], '2024-01-15'),
('interval 3 single day', ['2024-05-06', 3, [4], 0, 3], '2024-06-21'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None)],
[('multiple of weekday count', ['2024-01-01', 1, [0, 2, 4], 0, 6], '2024-01-12'),
('partial first week', ['2024-01-04', 1, [0, 2, 4], 0, 5], '2024-01-15'),
('interval 3 single day', ['2024-05-06', 3, [4], 0, 3], '2024-06-21'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None),
('within first week', ['2024-01-01', 2, [0, 1, 2], 0, 2], '2024-01-02'),
('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23')],
[('interval 3 single day', ['2024-05-06', 3, [4], 0, 3], '2024-06-21'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None),
('within first week', ['2024-01-01', 2, [0, 1, 2], 0, 2], '2024-01-02'),
('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23'),
('WKST=WE interval 2', ['2024-06-04', 2, [0, 3], 2, 7], '2024-07-25'),
('dtstart after all first-week days', ['2024-01-06', 2, [0, 1], 0, 5], '2024-02-12')],
[('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None),
('within first week', ['2024-01-01', 2, [0, 1, 2], 0, 2], '2024-01-02'),
('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23'),
('WKST=WE interval 2', ['2024-06-04', 2, [0, 3], 2, 7], '2024-07-25'),
('dtstart after all first-week days', ['2024-01-06', 2, [0, 1], 0, 5], '2024-02-12'),
('long series', ['2025-02-03', 2, [1, 3, 5], 0, 11], '2025-03-20'),
('regression: WKST=SU interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 6, 4], '1997-08-31'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None)],
[('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23'),
('WKST=WE interval 2', ['2024-06-04', 2, [0, 3], 2, 7], '2024-07-25'),
('dtstart after all first-week days', ['2024-01-06', 2, [0, 1], 0, 5], '2024-02-12'),
('long series', ['2025-02-03', 2, [1, 3, 5], 0, 11], '2025-03-20'),
('regression: WKST=SU interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 6, 4], '1997-08-31'),
('WKST=MO interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 0, 4], '1997-08-24'),
('multiple of weekday count', ['2024-01-01', 1, [0, 2, 4], 0, 6], '2024-01-12'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: WKST=SU interval 2 TU,SU | 1997-08-31 | 1997-08-31 | Passed |
| WKST=MO interval 2 TU,SU | 1997-08-24 | 1997-08-24 | Passed |
| multiple of weekday count | 2024-01-12 | 2024-01-12 | Passed |
| partial first week | 2024-01-15 | 2024-01-15 | Passed |
| interval 3 single day | 2024-06-21 | 2024-06-21 | Passed |
| count zero | None | None | Passed |
| count negative | 2024-01-01 | None | Failed |
SHA-256 / 0186378e00dffc5054fc292df1231337d8657d5f382441a01c9f2bf18f79c111
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(dtstart, interval, byday, wkst, count):
start = dt.date.fromisoformat(dtstart)
if count < 1:
return None
days = sorted(set(byday), key=lambda w: (w - wkst) % 7)
week0 = start - dt.timedelta(days=(start.weekday() - wkst) % 7)
first_week = [w for w in days if (w - wkst) % 7 >= (start.weekday() - wkst) % 7]
if count <= len(first_week):
w = first_week[count - 1]
weeks = 0
else:
rest = count - len(first_week)
weeks = (rest - 1) // len(days) + 1
w = days[(rest - 1) % len(days)]
last = week0 + dt.timedelta(days=weeks * interval * 7 + (w - wkst) % 7)
return last.isoformat()
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: WKST=SU interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 6, 4], '1997-08-31'),
('WKST=MO interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 0, 4], '1997-08-24'),
('multiple of weekday count', ['2024-01-01', 1, [0, 2, 4], 0, 6], '2024-01-12'),
('partial first week', ['2024-01-04', 1, [0, 2, 4], 0, 5], '2024-01-15'),
('interval 3 single day', ['2024-05-06', 3, [4], 0, 3], '2024-06-21'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None)],
[('multiple of weekday count', ['2024-01-01', 1, [0, 2, 4], 0, 6], '2024-01-12'),
('partial first week', ['2024-01-04', 1, [0, 2, 4], 0, 5], '2024-01-15'),
('interval 3 single day', ['2024-05-06', 3, [4], 0, 3], '2024-06-21'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None),
('within first week', ['2024-01-01', 2, [0, 1, 2], 0, 2], '2024-01-02'),
('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23')],
[('interval 3 single day', ['2024-05-06', 3, [4], 0, 3], '2024-06-21'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None),
('within first week', ['2024-01-01', 2, [0, 1, 2], 0, 2], '2024-01-02'),
('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23'),
('WKST=WE interval 2', ['2024-06-04', 2, [0, 3], 2, 7], '2024-07-25'),
('dtstart after all first-week days', ['2024-01-06', 2, [0, 1], 0, 5], '2024-02-12')],
[('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None),
('within first week', ['2024-01-01', 2, [0, 1, 2], 0, 2], '2024-01-02'),
('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23'),
('WKST=WE interval 2', ['2024-06-04', 2, [0, 3], 2, 7], '2024-07-25'),
('dtstart after all first-week days', ['2024-01-06', 2, [0, 1], 0, 5], '2024-02-12'),
('long series', ['2025-02-03', 2, [1, 3, 5], 0, 11], '2025-03-20'),
('regression: WKST=SU interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 6, 4], '1997-08-31'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None)],
[('WKST=SU weekend', ['2024-03-09', 1, [5, 6], 6, 5], '2024-03-23'),
('WKST=WE interval 2', ['2024-06-04', 2, [0, 3], 2, 7], '2024-07-25'),
('dtstart after all first-week days', ['2024-01-06', 2, [0, 1], 0, 5], '2024-02-12'),
('long series', ['2025-02-03', 2, [1, 3, 5], 0, 11], '2025-03-20'),
('regression: WKST=SU interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 6, 4], '1997-08-31'),
('WKST=MO interval 2 TU,SU', ['1997-08-05', 2, [1, 6], 0, 4], '1997-08-24'),
('multiple of weekday count', ['2024-01-01', 1, [0, 2, 4], 0, 6], '2024-01-12'),
('count zero', ['2024-01-01', 1, [0], 0, 0], None),
('count negative', ['2024-01-01', 2, [0, 3], 0, -1], None)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: WKST=SU interval 2 TU,SU | 1997-08-31 | 1997-08-31 | Passed |
| WKST=MO interval 2 TU,SU | 1997-08-24 | 1997-08-24 | Passed |
| multiple of weekday count | 2024-01-12 | 2024-01-12 | Passed |
| partial first week | 2024-01-15 | 2024-01-15 | Passed |
| interval 3 single day | 2024-06-21 | 2024-06-21 | Passed |
| count zero | None | None | Passed |
| count negative | None | None | Passed |
SHA-256 / 11ec558024551a2737205d52a5df27387996acd0e6a1462eed581e8e84e3d94b
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:23.911816+00:00.
Case digest / 8db78af70ee6a6dce6eb3591fcf3985a8cf71bf3aec16c4ec05692a09c41b945