FA-76876 / Calendar recurrence rules / Open access
Monthly BYMONTHDAY expansion with negative and invalid days: invalid day policy · case 01
BYMONTHDAY=31 yields February 28 and April 30 instead of skipping those months.
ROOT CAUSE
Nonexistent month days are clamped into the month instead of being skipped.
VERIFIED REPAIR
At the invalid day policy decision use `if 1 <= day <= dim:; days.append(day)`, leaving the other decision sites of the model unchanged.
Unsuccessful approach: The partial repair `if day >= 1:; days.append(min(day, dim))` still clamps positive days beyond the month end.
Case contract
FREQ=MONTHLY with a BYMONTHDAY list. Positive values count from the first day, negative values from the last day (-1 is the last day). A value that does not exist in a month is skipped for that month, never clamped. Months step by interval from the dtstart month; instances before dtstart are dropped; coinciding values yield one instance. Return the first count ISO dates in chronological order.
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, monthdays, count):
start = dt.date.fromisoformat(dtstart)
out = []
for k in range(400):
mi = start.month - 1 + k * interval
y, m = start.year + mi // 12, mi % 12 + 1
dim = calendar.monthrange(y, m)[1]
days = []
for md in monthdays:
day = md if md > 0 else dim + md + 1
days.append(min(max(day, 1), dim))
for day in sorted(set(days)):
d = dt.date(y, m, day)
if d < start:
continue
if len(out) >= count:
return out
out.append(d.isoformat())
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31']),
('last day of month', ['2024-01-15', 1, [-1], 4], ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('31 and -1 coincide',
['2024-01-01', 1, [31, -1], 4],
['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('first and last listed last-first',
['2024-03-10', 1, [-1, 1], 5],
['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31']),
('crossing december interval 2',
['2024-11-05', 2, [5], 4],
['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']),
('december start interval 1',
['2024-12-10', 1, [10, -3], 4],
['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']),
('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03'])],
[('31 and -1 coincide',
['2024-01-01', 1, [31, -1], 4],
['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('first and last listed last-first',
['2024-03-10', 1, [-1, 1], 5],
['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31']),
('crossing december interval 2',
['2024-11-05', 2, [5], 4],
['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']),
('december start interval 1',
['2024-12-10', 1, [10, -3], 4],
['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']),
('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03']),
('negative beyond month',
['2023-02-01', 1, [-30], 4],
['2023-03-02', '2023-04-01', '2023-05-02', '2023-06-01']),
('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'])],
[('crossing december interval 2',
['2024-11-05', 2, [5], 4],
['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']),
('december start interval 1',
['2024-12-10', 1, [10, -3], 4],
['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']),
('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03']),
('negative beyond month',
['2023-02-01', 1, [-30], 4],
['2023-03-02', '2023-04-01', '2023-05-02', '2023-06-01']),
('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('count zero', ['2024-01-01', 1, [1], 0], []),
('leap february 29', ['2023-12-29', 2, [29], 4], ['2023-12-29', '2024-02-29', '2024-04-29', '2024-06-29']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'])],
[('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03']),
('negative beyond month',
['2023-02-01', 1, [-30], 4],
['2023-03-02', '2023-04-01', '2023-05-02', '2023-06-01']),
('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('count zero', ['2024-01-01', 1, [1], 0], []),
('leap february 29', ['2023-12-29', 2, [29], 4], ['2023-12-29', '2024-02-29', '2024-04-29', '2024-06-29']),
('dtstart equals listed day',
['2024-06-30', 1, [30, 1], 4],
['2024-06-30', '2024-07-01', '2024-07-30', '2024-08-01']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'])],
[('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('count zero', ['2024-01-01', 1, [1], 0], []),
('leap february 29', ['2023-12-29', 2, [29], 4], ['2023-12-29', '2024-02-29', '2024-04-29', '2024-06-29']),
('dtstart equals listed day',
['2024-06-30', 1, [30, 1], 4],
['2024-06-30', '2024-07-01', '2024-07-30', '2024-08-01']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31']),
('last day of month', ['2024-01-15', 1, [-1], 4], ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('31 and -1 coincide',
['2024-01-01', 1, [31, -1], 4],
['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'])]]
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: 31st skips short months | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30', '2024-05-31'] | ['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'] | Failed |
| last day of month | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | Passed |
| 31 and -1 coincide | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | Passed |
| first and last listed last-first | ['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31'] | ['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31'] | Passed |
| crossing december interval 2 | ['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05'] | ['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05'] | Passed |
| december start interval 1 | ['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29'] | ['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29'] | Passed |
| dtstart after listed day | ['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03'] | ['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03'] | Passed |
SHA-256 / 4bb34c9115c3eb30e6fd75312d780c69d89112447699f4b4e9b82231c5116670
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, monthdays, count):
start = dt.date.fromisoformat(dtstart)
out = []
for k in range(400):
mi = start.month - 1 + k * interval
y, m = start.year + mi // 12, mi % 12 + 1
dim = calendar.monthrange(y, m)[1]
days = []
for md in monthdays:
day = md if md > 0 else dim + md + 1
if day >= 1:
days.append(min(day, dim))
for day in sorted(set(days)):
d = dt.date(y, m, day)
if d < start:
continue
if len(out) >= count:
return out
out.append(d.isoformat())
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31']),
('last day of month', ['2024-01-15', 1, [-1], 4], ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('31 and -1 coincide',
['2024-01-01', 1, [31, -1], 4],
['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('first and last listed last-first',
['2024-03-10', 1, [-1, 1], 5],
['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31']),
('crossing december interval 2',
['2024-11-05', 2, [5], 4],
['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']),
('december start interval 1',
['2024-12-10', 1, [10, -3], 4],
['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']),
('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03'])],
[('31 and -1 coincide',
['2024-01-01', 1, [31, -1], 4],
['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('first and last listed last-first',
['2024-03-10', 1, [-1, 1], 5],
['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31']),
('crossing december interval 2',
['2024-11-05', 2, [5], 4],
['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']),
('december start interval 1',
['2024-12-10', 1, [10, -3], 4],
['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']),
('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03']),
('negative beyond month',
['2023-02-01', 1, [-30], 4],
['2023-03-02', '2023-04-01', '2023-05-02', '2023-06-01']),
('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'])],
[('crossing december interval 2',
['2024-11-05', 2, [5], 4],
['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']),
('december start interval 1',
['2024-12-10', 1, [10, -3], 4],
['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']),
('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03']),
('negative beyond month',
['2023-02-01', 1, [-30], 4],
['2023-03-02', '2023-04-01', '2023-05-02', '2023-06-01']),
('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('count zero', ['2024-01-01', 1, [1], 0], []),
('leap february 29', ['2023-12-29', 2, [29], 4], ['2023-12-29', '2024-02-29', '2024-04-29', '2024-06-29']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'])],
[('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03']),
('negative beyond month',
['2023-02-01', 1, [-30], 4],
['2023-03-02', '2023-04-01', '2023-05-02', '2023-06-01']),
('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('count zero', ['2024-01-01', 1, [1], 0], []),
('leap february 29', ['2023-12-29', 2, [29], 4], ['2023-12-29', '2024-02-29', '2024-04-29', '2024-06-29']),
('dtstart equals listed day',
['2024-06-30', 1, [30, 1], 4],
['2024-06-30', '2024-07-01', '2024-07-30', '2024-08-01']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'])],
[('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('count zero', ['2024-01-01', 1, [1], 0], []),
('leap february 29', ['2023-12-29', 2, [29], 4], ['2023-12-29', '2024-02-29', '2024-04-29', '2024-06-29']),
('dtstart equals listed day',
['2024-06-30', 1, [30, 1], 4],
['2024-06-30', '2024-07-01', '2024-07-30', '2024-08-01']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31']),
('last day of month', ['2024-01-15', 1, [-1], 4], ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('31 and -1 coincide',
['2024-01-01', 1, [31, -1], 4],
['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'])]]
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: 31st skips short months | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30', '2024-05-31'] | ['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'] | Failed |
| last day of month | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | Passed |
| 31 and -1 coincide | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | Passed |
| first and last listed last-first | ['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31'] | ['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31'] | Passed |
| crossing december interval 2 | ['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05'] | ['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05'] | Passed |
| december start interval 1 | ['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29'] | ['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29'] | Passed |
| dtstart after listed day | ['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03'] | ['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03'] | Passed |
SHA-256 / b3fc8b7d91f20b4d2196f80487ef97d7dc6e148a27d27d3257af5589b85e351a
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, monthdays, count):
start = dt.date.fromisoformat(dtstart)
out = []
for k in range(400):
mi = start.month - 1 + k * interval
y, m = start.year + mi // 12, mi % 12 + 1
dim = calendar.monthrange(y, m)[1]
days = []
for md in monthdays:
day = md if md > 0 else dim + md + 1
if 1 <= day <= dim:
days.append(day)
for day in sorted(set(days)):
d = dt.date(y, m, day)
if d < start:
continue
if len(out) >= count:
return out
out.append(d.isoformat())
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31']),
('last day of month', ['2024-01-15', 1, [-1], 4], ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('31 and -1 coincide',
['2024-01-01', 1, [31, -1], 4],
['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('first and last listed last-first',
['2024-03-10', 1, [-1, 1], 5],
['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31']),
('crossing december interval 2',
['2024-11-05', 2, [5], 4],
['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']),
('december start interval 1',
['2024-12-10', 1, [10, -3], 4],
['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']),
('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03'])],
[('31 and -1 coincide',
['2024-01-01', 1, [31, -1], 4],
['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('first and last listed last-first',
['2024-03-10', 1, [-1, 1], 5],
['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31']),
('crossing december interval 2',
['2024-11-05', 2, [5], 4],
['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']),
('december start interval 1',
['2024-12-10', 1, [10, -3], 4],
['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']),
('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03']),
('negative beyond month',
['2023-02-01', 1, [-30], 4],
['2023-03-02', '2023-04-01', '2023-05-02', '2023-06-01']),
('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'])],
[('crossing december interval 2',
['2024-11-05', 2, [5], 4],
['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']),
('december start interval 1',
['2024-12-10', 1, [10, -3], 4],
['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']),
('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03']),
('negative beyond month',
['2023-02-01', 1, [-30], 4],
['2023-03-02', '2023-04-01', '2023-05-02', '2023-06-01']),
('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('count zero', ['2024-01-01', 1, [1], 0], []),
('leap february 29', ['2023-12-29', 2, [29], 4], ['2023-12-29', '2024-02-29', '2024-04-29', '2024-06-29']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'])],
[('dtstart after listed day',
['2024-05-20', 1, [3, 25], 4],
['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03']),
('negative beyond month',
['2023-02-01', 1, [-30], 4],
['2023-03-02', '2023-04-01', '2023-05-02', '2023-06-01']),
('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('count zero', ['2024-01-01', 1, [1], 0], []),
('leap february 29', ['2023-12-29', 2, [29], 4], ['2023-12-29', '2024-02-29', '2024-04-29', '2024-06-29']),
('dtstart equals listed day',
['2024-06-30', 1, [30, 1], 4],
['2024-06-30', '2024-07-01', '2024-07-30', '2024-08-01']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'])],
[('interval 3 from october',
['2023-10-15', 3, [15, -1], 5],
['2023-10-15', '2023-10-31', '2024-01-15', '2024-01-31', '2024-04-15']),
('count zero', ['2024-01-01', 1, [1], 0], []),
('leap february 29', ['2023-12-29', 2, [29], 4], ['2023-12-29', '2024-02-29', '2024-04-29', '2024-06-29']),
('dtstart equals listed day',
['2024-06-30', 1, [30, 1], 4],
['2024-06-30', '2024-07-01', '2024-07-30', '2024-08-01']),
('regression: 31st skips short months',
['2024-01-31', 1, [31], 5],
['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31']),
('last day of month', ['2024-01-15', 1, [-1], 4], ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30']),
('31 and -1 coincide',
['2024-01-01', 1, [31, -1], 4],
['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'])]]
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: 31st skips short months | ['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'] | ['2024-01-31', '2024-03-31', '2024-05-31', '2024-07-31', '2024-08-31'] | Passed |
| last day of month | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | Passed |
| 31 and -1 coincide | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | ['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30'] | Passed |
| first and last listed last-first | ['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31'] | ['2024-03-31', '2024-04-01', '2024-04-30', '2024-05-01', '2024-05-31'] | Passed |
| crossing december interval 2 | ['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05'] | ['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05'] | Passed |
| december start interval 1 | ['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29'] | ['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29'] | Passed |
| dtstart after listed day | ['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03'] | ['2024-05-25', '2024-06-03', '2024-06-25', '2024-07-03'] | Passed |
SHA-256 / 8046e0e44a980a18bfcd18e9c602cb73903af0aee2f1d6fd769d705a2d766638
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:20.367207+00:00.
Case digest / 0f39a2f894d64b381923ecc5060950783dbb4ea3cad9947d0c10c7b6b937eab4