FAILURE MAP
← Case archive

FA-76866 / Calendar recurrence rules / Open access

Monthly BYMONTHDAY expansion with negative and invalid days: year carry · case 01

A series that crosses December reports January instances in the previous year.

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

ROOT CAUSE

The year carry is computed from the elapsed month count alone, ignoring the starting month offset.

VERIFIED REPAIR

At the year carry decision use `start.year + mi // 12, mi % 12 + 1`, leaving the other decision sites of the model unchanged.

Unsuccessful approach: The partial repair `start.year + (k * interval + start.month) // 12, mi % 12 + 1` adds the 1-based start month, so a December start is carried into the next year one month early.

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 + (k * interval) // 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'])],
 [('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'])],
 [('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 fixtureActualExpectedOutcome
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-11-05', '2025-01-05', '2025-03-05']['2024-11-05', '2025-01-05', '2025-03-05', '2025-05-05']Failed
december start interval 1['2024-12-10', '2024-12-29', '2025-12-10', '2025-12-29']['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']Failed
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 / 9443c694fc5b1edbeb23c7805b83d060a00e921ef1d4d053449f2827c8a4a881

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 + (k * interval + start.month) // 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'])],
 [('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'])],
 [('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 fixtureActualExpectedOutcome
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['2025-12-10', '2025-12-29', '2025-01-10', '2025-01-29']['2024-12-10', '2024-12-29', '2025-01-10', '2025-01-29']Failed
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 / ceb1812761b161ac220e2eb07726c05704e4054879bdb09938d5a0db7f71379b

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'])],
 [('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'])],
 [('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 fixtureActualExpectedOutcome
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 / 24f86a619e738b9242285e8b283eafc092cc2190db6f08a2bed0fd4fee2f82d7

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.324210+00:00.

Case digest / 103a342138a786756fa2007f364d11ec7fe93dda513d28927d013c472c19f97a