FA-77216 / Calendar recurrence rules / Open access
Parsing and validating RRULE property text: name case · case 01
A rule written as "freq=weekly" is rejected as missing FREQ.
ROOT CAUSE
Part names are compared case-sensitively.
VERIFIED REPAIR
At the name case decision use `name.upper()`, leaving the other decision sites of the model unchanged.
Unsuccessful approach: The partial repair `name.strip()` trims whitespace but still keeps the name case-sensitive.
Case contract
Parse "NAME=VALUE;..." rule text. Part names are case-insensitive; empty parts (a trailing ";") are ignored; a part without "=" is malformed; any repeated part name is an error; FREQ is required. INTERVAL defaults to 1 and must be >= 1. BYDAY tokens are an optional signed 1-2 digit ordinal (explicit "+" allowed) followed by MO..SU; a present ordinal must satisfy 1 <= |n| <= 53. Errors are returned as {"error": message}; otherwise {"freq","interval","byday":[[n, day]],"count","until"}.
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 re
N = 1
observations = []
def solve(text):
parts = {}
for chunk in text.split(';'):
if not chunk:
continue
if '=' not in chunk:
return {'error': 'malformed'}
name, value = chunk.split('=', 1)
name = name
if name in parts:
return {'error': 'duplicate ' + name}
parts[name] = value
if 'FREQ' not in parts:
return {'error': 'missing FREQ'}
interval = int(parts.get('INTERVAL', '1'))
if interval < 1:
return {'error': 'bad INTERVAL'}
days = []
for token in (parts['BYDAY'].split(',') if 'BYDAY' in parts else []):
m = re.fullmatch(r'([+-]?\d{1,2})?(MO|TU|WE|TH|FR|SA|SU)', token)
if not m:
return {'error': 'bad BYDAY ' + token}
n = int(m.group(1)) if m.group(1) else 0
if m.group(1) and not 1 <= abs(n) <= 53:
return {'error': 'bad ordinal'}
days.append([n, m.group(2)])
return {'freq': parts['FREQ'], 'interval': interval, 'byday': days,
'count': int(parts['COUNT']) if 'COUNT' in parts else None, 'until': parts.get('UNTIL')}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: lowercase names',
['freq=WEEKLY;interval=2;byday=MO,WE'],
{'freq': 'WEEKLY', 'interval': 2, 'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'until': None}),
('duplicate count', ['FREQ=DAILY;COUNT=3;COUNT=5'], {'error': 'duplicate COUNT'}),
('identical duplicate', ['FREQ=DAILY;COUNT=3;COUNT=3'], {'error': 'duplicate COUNT'}),
('interval zero', ['FREQ=DAILY;INTERVAL=0'], {'error': 'bad INTERVAL'}),
('interval negative', ['FREQ=DAILY;INTERVAL=-2'], {'error': 'bad INTERVAL'}),
('plus ordinal',
['FREQ=MONTHLY;BYDAY=+2TU'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[2, 'TU']], 'count': None, 'until': None}),
('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None})],
[('identical duplicate', ['FREQ=DAILY;COUNT=3;COUNT=3'], {'error': 'duplicate COUNT'}),
('interval zero', ['FREQ=DAILY;INTERVAL=0'], {'error': 'bad INTERVAL'}),
('interval negative', ['FREQ=DAILY;INTERVAL=-2'], {'error': 'bad INTERVAL'}),
('plus ordinal',
['FREQ=MONTHLY;BYDAY=+2TU'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[2, 'TU']], 'count': None, 'until': None}),
('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None}),
('zero ordinal', ['FREQ=MONTHLY;BYDAY=0MO'], {'error': 'bad ordinal'}),
('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('regression: lowercase names',
['freq=WEEKLY;interval=2;byday=MO,WE'],
{'freq': 'WEEKLY', 'interval': 2, 'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'until': None})],
[('interval negative', ['FREQ=DAILY;INTERVAL=-2'], {'error': 'bad INTERVAL'}),
('plus ordinal',
['FREQ=MONTHLY;BYDAY=+2TU'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[2, 'TU']], 'count': None, 'until': None}),
('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None}),
('zero ordinal', ['FREQ=MONTHLY;BYDAY=0MO'], {'error': 'bad ordinal'}),
('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('ordinal too large', ['FREQ=YEARLY;BYDAY=54MO'], {'error': 'bad ordinal'}),
('trailing semicolon',
['FREQ=WEEKLY;UNTIL=20240301;'],
{'freq': 'WEEKLY', 'interval': 1, 'byday': [], 'count': None, 'until': '20240301'}),
('mixed-case duplicate', ['FREQ=DAILY;Count=2;COUNT=4'], {'error': 'duplicate COUNT'})],
[('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None}),
('zero ordinal', ['FREQ=MONTHLY;BYDAY=0MO'], {'error': 'bad ordinal'}),
('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('ordinal too large', ['FREQ=YEARLY;BYDAY=54MO'], {'error': 'bad ordinal'}),
('trailing semicolon',
['FREQ=WEEKLY;UNTIL=20240301;'],
{'freq': 'WEEKLY', 'interval': 1, 'byday': [], 'count': None, 'until': '20240301'}),
('missing freq', ['COUNT=3;BYDAY=MO'], {'error': 'missing FREQ'}),
('mixed-case duplicate', ['FREQ=DAILY;Count=2;COUNT=4'], {'error': 'duplicate COUNT'})],
[('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('ordinal too large', ['FREQ=YEARLY;BYDAY=54MO'], {'error': 'bad ordinal'}),
('trailing semicolon',
['FREQ=WEEKLY;UNTIL=20240301;'],
{'freq': 'WEEKLY', 'interval': 1, 'byday': [], 'count': None, 'until': '20240301'}),
('missing freq', ['COUNT=3;BYDAY=MO'], {'error': 'missing FREQ'}),
('mixed-case duplicate', ['FREQ=DAILY;Count=2;COUNT=4'], {'error': 'duplicate COUNT'}),
('regression: lowercase names',
['freq=WEEKLY;interval=2;byday=MO,WE'],
{'freq': 'WEEKLY', 'interval': 2, 'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'until': None}),
('duplicate count', ['FREQ=DAILY;COUNT=3;COUNT=5'], {'error': 'duplicate COUNT'})]]
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: lowercase names | {'error': 'missing FREQ'} | {'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'freq': 'WEEKLY', 'interval': 2, 'until': None} | Failed |
| duplicate count | {'error': 'duplicate COUNT'} | {'error': 'duplicate COUNT'} | Passed |
| identical duplicate | {'error': 'duplicate COUNT'} | {'error': 'duplicate COUNT'} | Passed |
| interval zero | {'error': 'bad INTERVAL'} | {'error': 'bad INTERVAL'} | Passed |
| interval negative | {'error': 'bad INTERVAL'} | {'error': 'bad INTERVAL'} | Passed |
| plus ordinal | {'byday': [[2, 'TU']], 'count': None, 'freq': 'MONTHLY', 'interval': 1, 'until': None} | {'byday': [[2, 'TU']], 'count': None, 'freq': 'MONTHLY', 'interval': 1, 'until': None} | Passed |
| two digit ordinal | {'byday': [[20, 'MO']], 'count': None, 'freq': 'YEARLY', 'interval': 1, 'until': None} | {'byday': [[20, 'MO']], 'count': None, 'freq': 'YEARLY', 'interval': 1, 'until': None} | Passed |
SHA-256 / fb35dda8428e82423b398ab54e5e1572f22d77903cf34d7d53e3c01d479aa6da
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(text):
parts = {}
for chunk in text.split(';'):
if not chunk:
continue
if '=' not in chunk:
return {'error': 'malformed'}
name, value = chunk.split('=', 1)
name = name.strip()
if name in parts:
return {'error': 'duplicate ' + name}
parts[name] = value
if 'FREQ' not in parts:
return {'error': 'missing FREQ'}
interval = int(parts.get('INTERVAL', '1'))
if interval < 1:
return {'error': 'bad INTERVAL'}
days = []
for token in (parts['BYDAY'].split(',') if 'BYDAY' in parts else []):
m = re.fullmatch(r'([+-]?\d{1,2})?(MO|TU|WE|TH|FR|SA|SU)', token)
if not m:
return {'error': 'bad BYDAY ' + token}
n = int(m.group(1)) if m.group(1) else 0
if m.group(1) and not 1 <= abs(n) <= 53:
return {'error': 'bad ordinal'}
days.append([n, m.group(2)])
return {'freq': parts['FREQ'], 'interval': interval, 'byday': days,
'count': int(parts['COUNT']) if 'COUNT' in parts else None, 'until': parts.get('UNTIL')}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: lowercase names',
['freq=WEEKLY;interval=2;byday=MO,WE'],
{'freq': 'WEEKLY', 'interval': 2, 'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'until': None}),
('duplicate count', ['FREQ=DAILY;COUNT=3;COUNT=5'], {'error': 'duplicate COUNT'}),
('identical duplicate', ['FREQ=DAILY;COUNT=3;COUNT=3'], {'error': 'duplicate COUNT'}),
('interval zero', ['FREQ=DAILY;INTERVAL=0'], {'error': 'bad INTERVAL'}),
('interval negative', ['FREQ=DAILY;INTERVAL=-2'], {'error': 'bad INTERVAL'}),
('plus ordinal',
['FREQ=MONTHLY;BYDAY=+2TU'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[2, 'TU']], 'count': None, 'until': None}),
('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None})],
[('identical duplicate', ['FREQ=DAILY;COUNT=3;COUNT=3'], {'error': 'duplicate COUNT'}),
('interval zero', ['FREQ=DAILY;INTERVAL=0'], {'error': 'bad INTERVAL'}),
('interval negative', ['FREQ=DAILY;INTERVAL=-2'], {'error': 'bad INTERVAL'}),
('plus ordinal',
['FREQ=MONTHLY;BYDAY=+2TU'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[2, 'TU']], 'count': None, 'until': None}),
('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None}),
('zero ordinal', ['FREQ=MONTHLY;BYDAY=0MO'], {'error': 'bad ordinal'}),
('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('regression: lowercase names',
['freq=WEEKLY;interval=2;byday=MO,WE'],
{'freq': 'WEEKLY', 'interval': 2, 'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'until': None})],
[('interval negative', ['FREQ=DAILY;INTERVAL=-2'], {'error': 'bad INTERVAL'}),
('plus ordinal',
['FREQ=MONTHLY;BYDAY=+2TU'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[2, 'TU']], 'count': None, 'until': None}),
('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None}),
('zero ordinal', ['FREQ=MONTHLY;BYDAY=0MO'], {'error': 'bad ordinal'}),
('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('ordinal too large', ['FREQ=YEARLY;BYDAY=54MO'], {'error': 'bad ordinal'}),
('trailing semicolon',
['FREQ=WEEKLY;UNTIL=20240301;'],
{'freq': 'WEEKLY', 'interval': 1, 'byday': [], 'count': None, 'until': '20240301'}),
('mixed-case duplicate', ['FREQ=DAILY;Count=2;COUNT=4'], {'error': 'duplicate COUNT'})],
[('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None}),
('zero ordinal', ['FREQ=MONTHLY;BYDAY=0MO'], {'error': 'bad ordinal'}),
('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('ordinal too large', ['FREQ=YEARLY;BYDAY=54MO'], {'error': 'bad ordinal'}),
('trailing semicolon',
['FREQ=WEEKLY;UNTIL=20240301;'],
{'freq': 'WEEKLY', 'interval': 1, 'byday': [], 'count': None, 'until': '20240301'}),
('missing freq', ['COUNT=3;BYDAY=MO'], {'error': 'missing FREQ'}),
('mixed-case duplicate', ['FREQ=DAILY;Count=2;COUNT=4'], {'error': 'duplicate COUNT'})],
[('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('ordinal too large', ['FREQ=YEARLY;BYDAY=54MO'], {'error': 'bad ordinal'}),
('trailing semicolon',
['FREQ=WEEKLY;UNTIL=20240301;'],
{'freq': 'WEEKLY', 'interval': 1, 'byday': [], 'count': None, 'until': '20240301'}),
('missing freq', ['COUNT=3;BYDAY=MO'], {'error': 'missing FREQ'}),
('mixed-case duplicate', ['FREQ=DAILY;Count=2;COUNT=4'], {'error': 'duplicate COUNT'}),
('regression: lowercase names',
['freq=WEEKLY;interval=2;byday=MO,WE'],
{'freq': 'WEEKLY', 'interval': 2, 'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'until': None}),
('duplicate count', ['FREQ=DAILY;COUNT=3;COUNT=5'], {'error': 'duplicate COUNT'})]]
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: lowercase names | {'error': 'missing FREQ'} | {'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'freq': 'WEEKLY', 'interval': 2, 'until': None} | Failed |
| duplicate count | {'error': 'duplicate COUNT'} | {'error': 'duplicate COUNT'} | Passed |
| identical duplicate | {'error': 'duplicate COUNT'} | {'error': 'duplicate COUNT'} | Passed |
| interval zero | {'error': 'bad INTERVAL'} | {'error': 'bad INTERVAL'} | Passed |
| interval negative | {'error': 'bad INTERVAL'} | {'error': 'bad INTERVAL'} | Passed |
| plus ordinal | {'byday': [[2, 'TU']], 'count': None, 'freq': 'MONTHLY', 'interval': 1, 'until': None} | {'byday': [[2, 'TU']], 'count': None, 'freq': 'MONTHLY', 'interval': 1, 'until': None} | Passed |
| two digit ordinal | {'byday': [[20, 'MO']], 'count': None, 'freq': 'YEARLY', 'interval': 1, 'until': None} | {'byday': [[20, 'MO']], 'count': None, 'freq': 'YEARLY', 'interval': 1, 'until': None} | Passed |
SHA-256 / f16ff11439d422138b14b5bf7b5fddb486b9d35b822f956935e8c7d67ea1a796
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(text):
parts = {}
for chunk in text.split(';'):
if not chunk:
continue
if '=' not in chunk:
return {'error': 'malformed'}
name, value = chunk.split('=', 1)
name = name.upper()
if name in parts:
return {'error': 'duplicate ' + name}
parts[name] = value
if 'FREQ' not in parts:
return {'error': 'missing FREQ'}
interval = int(parts.get('INTERVAL', '1'))
if interval < 1:
return {'error': 'bad INTERVAL'}
days = []
for token in (parts['BYDAY'].split(',') if 'BYDAY' in parts else []):
m = re.fullmatch(r'([+-]?\d{1,2})?(MO|TU|WE|TH|FR|SA|SU)', token)
if not m:
return {'error': 'bad BYDAY ' + token}
n = int(m.group(1)) if m.group(1) else 0
if m.group(1) and not 1 <= abs(n) <= 53:
return {'error': 'bad ordinal'}
days.append([n, m.group(2)])
return {'freq': parts['FREQ'], 'interval': interval, 'byday': days,
'count': int(parts['COUNT']) if 'COUNT' in parts else None, 'until': parts.get('UNTIL')}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: lowercase names',
['freq=WEEKLY;interval=2;byday=MO,WE'],
{'freq': 'WEEKLY', 'interval': 2, 'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'until': None}),
('duplicate count', ['FREQ=DAILY;COUNT=3;COUNT=5'], {'error': 'duplicate COUNT'}),
('identical duplicate', ['FREQ=DAILY;COUNT=3;COUNT=3'], {'error': 'duplicate COUNT'}),
('interval zero', ['FREQ=DAILY;INTERVAL=0'], {'error': 'bad INTERVAL'}),
('interval negative', ['FREQ=DAILY;INTERVAL=-2'], {'error': 'bad INTERVAL'}),
('plus ordinal',
['FREQ=MONTHLY;BYDAY=+2TU'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[2, 'TU']], 'count': None, 'until': None}),
('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None})],
[('identical duplicate', ['FREQ=DAILY;COUNT=3;COUNT=3'], {'error': 'duplicate COUNT'}),
('interval zero', ['FREQ=DAILY;INTERVAL=0'], {'error': 'bad INTERVAL'}),
('interval negative', ['FREQ=DAILY;INTERVAL=-2'], {'error': 'bad INTERVAL'}),
('plus ordinal',
['FREQ=MONTHLY;BYDAY=+2TU'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[2, 'TU']], 'count': None, 'until': None}),
('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None}),
('zero ordinal', ['FREQ=MONTHLY;BYDAY=0MO'], {'error': 'bad ordinal'}),
('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('regression: lowercase names',
['freq=WEEKLY;interval=2;byday=MO,WE'],
{'freq': 'WEEKLY', 'interval': 2, 'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'until': None})],
[('interval negative', ['FREQ=DAILY;INTERVAL=-2'], {'error': 'bad INTERVAL'}),
('plus ordinal',
['FREQ=MONTHLY;BYDAY=+2TU'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[2, 'TU']], 'count': None, 'until': None}),
('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None}),
('zero ordinal', ['FREQ=MONTHLY;BYDAY=0MO'], {'error': 'bad ordinal'}),
('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('ordinal too large', ['FREQ=YEARLY;BYDAY=54MO'], {'error': 'bad ordinal'}),
('trailing semicolon',
['FREQ=WEEKLY;UNTIL=20240301;'],
{'freq': 'WEEKLY', 'interval': 1, 'byday': [], 'count': None, 'until': '20240301'}),
('mixed-case duplicate', ['FREQ=DAILY;Count=2;COUNT=4'], {'error': 'duplicate COUNT'})],
[('two digit ordinal',
['FREQ=YEARLY;BYDAY=20MO'],
{'freq': 'YEARLY', 'interval': 1, 'byday': [[20, 'MO']], 'count': None, 'until': None}),
('zero ordinal', ['FREQ=MONTHLY;BYDAY=0MO'], {'error': 'bad ordinal'}),
('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('ordinal too large', ['FREQ=YEARLY;BYDAY=54MO'], {'error': 'bad ordinal'}),
('trailing semicolon',
['FREQ=WEEKLY;UNTIL=20240301;'],
{'freq': 'WEEKLY', 'interval': 1, 'byday': [], 'count': None, 'until': '20240301'}),
('missing freq', ['COUNT=3;BYDAY=MO'], {'error': 'missing FREQ'}),
('mixed-case duplicate', ['FREQ=DAILY;Count=2;COUNT=4'], {'error': 'duplicate COUNT'})],
[('negative ordinal',
['FREQ=MONTHLY;BYDAY=-1FR;COUNT=4'],
{'freq': 'MONTHLY', 'interval': 1, 'byday': [[-1, 'FR']], 'count': 4, 'until': None}),
('ordinal too large', ['FREQ=YEARLY;BYDAY=54MO'], {'error': 'bad ordinal'}),
('trailing semicolon',
['FREQ=WEEKLY;UNTIL=20240301;'],
{'freq': 'WEEKLY', 'interval': 1, 'byday': [], 'count': None, 'until': '20240301'}),
('missing freq', ['COUNT=3;BYDAY=MO'], {'error': 'missing FREQ'}),
('mixed-case duplicate', ['FREQ=DAILY;Count=2;COUNT=4'], {'error': 'duplicate COUNT'}),
('regression: lowercase names',
['freq=WEEKLY;interval=2;byday=MO,WE'],
{'freq': 'WEEKLY', 'interval': 2, 'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'until': None}),
('duplicate count', ['FREQ=DAILY;COUNT=3;COUNT=5'], {'error': 'duplicate COUNT'})]]
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: lowercase names | {'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'freq': 'WEEKLY', 'interval': 2, 'until': None} | {'byday': [[0, 'MO'], [0, 'WE']], 'count': None, 'freq': 'WEEKLY', 'interval': 2, 'until': None} | Passed |
| duplicate count | {'error': 'duplicate COUNT'} | {'error': 'duplicate COUNT'} | Passed |
| identical duplicate | {'error': 'duplicate COUNT'} | {'error': 'duplicate COUNT'} | Passed |
| interval zero | {'error': 'bad INTERVAL'} | {'error': 'bad INTERVAL'} | Passed |
| interval negative | {'error': 'bad INTERVAL'} | {'error': 'bad INTERVAL'} | Passed |
| plus ordinal | {'byday': [[2, 'TU']], 'count': None, 'freq': 'MONTHLY', 'interval': 1, 'until': None} | {'byday': [[2, 'TU']], 'count': None, 'freq': 'MONTHLY', 'interval': 1, 'until': None} | Passed |
| two digit ordinal | {'byday': [[20, 'MO']], 'count': None, 'freq': 'YEARLY', 'interval': 1, 'until': None} | {'byday': [[20, 'MO']], 'count': None, 'freq': 'YEARLY', 'interval': 1, 'until': None} | Passed |
SHA-256 / 074a051995f1b112daad566f0e8e25b446bbb294850c4917a8606e7e235f5254
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.600250+00:00.
Case digest / d7b9b7ae7b60cc56c44a044d1faf967d365fc67d1df269224192b26bef4b296c