FA-77211 / Calendar recurrence rules / Open access
UNTIL value forms and COUNT/UNTIL precedence for timed series: count stop · case 01
A series with both COUNT and UNTIL runs past COUNT until UNTIL is reached.
ROOT CAUSE
COUNT is ignored whenever UNTIL is present.
VERIFIED REPAIR
At the count stop decision use `count is not None and len(out) >= count`, leaving the other decision sites of the model unchanged.
Unsuccessful approach: The partial repair `count and len(out) >= count` treats COUNT=0 as unbounded.
Case contract
A daily-interval timed series in a fixed local offset (offset_min east of UTC). until may be None, a date (inclusive through the end of that local day, i.e. 23:59), a local date-time (inclusive), or a UTC date-time ending in Z (converted to local by adding offset_min). count may be None; count 0 means no instances. When both are given the series stops at whichever limit is reached first. Unbounded series are capped at 40 instances. Return ISO local date-times.
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, count, until, offset_min):
first = dt.datetime.fromisoformat(dtstart)
if until is None:
limit = None
elif until.endswith('Z'):
limit = dt.datetime.fromisoformat(until[:-1]) + dt.timedelta(minutes=offset_min)
elif len(until) == 10:
limit = dt.datetime.combine(dt.date.fromisoformat(until), dt.time(23, 59))
else:
limit = dt.datetime.fromisoformat(until)
out = []
for k in range(40):
t = first + dt.timedelta(days=k * interval)
if limit is not None and t > limit:
break
if count is not None and limit is None and len(out) >= count:
break
out.append(t.isoformat(timespec='minutes'))
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: count and until both set',
['2024-01-01T09:00', 1, 3, '2024-01-10', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('date until includes that day',
['2024-01-01T09:00', 2, None, '2024-01-07', 0],
['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00']),
('date until evening event',
['2024-01-01T20:00', 1, None, '2024-01-03', 60],
['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00']),
('local until exact',
['2024-01-01T09:00', 1, None, '2024-01-04T09:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00']),
('local until earlier time',
['2024-01-01T09:00', 1, None, '2024-01-04T08:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until east offset',
['2024-01-01T09:00', 1, None, '2024-01-03T07:00Z', 120],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], [])],
[('date until evening event',
['2024-01-01T20:00', 1, None, '2024-01-03', 60],
['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00']),
('local until exact',
['2024-01-01T09:00', 1, None, '2024-01-04T09:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00']),
('local until earlier time',
['2024-01-01T09:00', 1, None, '2024-01-04T08:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until east offset',
['2024-01-01T09:00', 1, None, '2024-01-03T07:00Z', 120],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], []),
('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], [])],
[('local until earlier time',
['2024-01-01T09:00', 1, None, '2024-01-04T08:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until east offset',
['2024-01-01T09:00', 1, None, '2024-01-03T07:00Z', 120],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], []),
('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], []),
('until before count reached',
['2024-01-01T09:00', 3, 10, '2024-01-08', 0],
['2024-01-01T09:00', '2024-01-04T09:00', '2024-01-07T09:00']),
('count before until reached',
['2024-03-01T18:30', 7, 2, '2024-12-31T00:00Z', 60],
['2024-03-01T18:30', '2024-03-08T18:30'])],
[('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], []),
('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], []),
('until before count reached',
['2024-01-01T09:00', 3, 10, '2024-01-08', 0],
['2024-01-01T09:00', '2024-01-04T09:00', '2024-01-07T09:00']),
('count before until reached',
['2024-03-01T18:30', 7, 2, '2024-12-31T00:00Z', 60],
['2024-03-01T18:30', '2024-03-08T18:30']),
('regression: count and until both set',
['2024-01-01T09:00', 1, 3, '2024-01-10', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('date until includes that day',
['2024-01-01T09:00', 2, None, '2024-01-07', 0],
['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00'])],
[('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], []),
('until before count reached',
['2024-01-01T09:00', 3, 10, '2024-01-08', 0],
['2024-01-01T09:00', '2024-01-04T09:00', '2024-01-07T09:00']),
('count before until reached',
['2024-03-01T18:30', 7, 2, '2024-12-31T00:00Z', 60],
['2024-03-01T18:30', '2024-03-08T18:30']),
('regression: count and until both set',
['2024-01-01T09:00', 1, 3, '2024-01-10', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('date until includes that day',
['2024-01-01T09:00', 2, None, '2024-01-07', 0],
['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00']),
('date until evening event',
['2024-01-01T20:00', 1, None, '2024-01-03', 60],
['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00']),
('local until exact',
['2024-01-01T09:00', 1, None, '2024-01-04T09:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00'])]]
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: count and until both set | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00', '2024-01-05T09:00', '2024-01-06T09:00', '2024-01-07T09:00', '2024-01-08T09:00', '2024-01-09T09:00', '2024-01-10T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Failed |
| date until includes that day | ['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00'] | ['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00'] | Passed |
| date until evening event | ['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00'] | ['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00'] | Passed |
| local until exact | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00'] | Passed |
| local until earlier time | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| utc until east offset | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| utc until west offset | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| count zero | [] | [] | Passed |
SHA-256 / 9b84d137f0f70b253afc105ba63cb03a88c7ab45d5d0dbdde733e7f23b588550
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, count, until, offset_min):
first = dt.datetime.fromisoformat(dtstart)
if until is None:
limit = None
elif until.endswith('Z'):
limit = dt.datetime.fromisoformat(until[:-1]) + dt.timedelta(minutes=offset_min)
elif len(until) == 10:
limit = dt.datetime.combine(dt.date.fromisoformat(until), dt.time(23, 59))
else:
limit = dt.datetime.fromisoformat(until)
out = []
for k in range(40):
t = first + dt.timedelta(days=k * interval)
if limit is not None and t > limit:
break
if count and len(out) >= count:
break
out.append(t.isoformat(timespec='minutes'))
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: count and until both set',
['2024-01-01T09:00', 1, 3, '2024-01-10', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('date until includes that day',
['2024-01-01T09:00', 2, None, '2024-01-07', 0],
['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00']),
('date until evening event',
['2024-01-01T20:00', 1, None, '2024-01-03', 60],
['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00']),
('local until exact',
['2024-01-01T09:00', 1, None, '2024-01-04T09:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00']),
('local until earlier time',
['2024-01-01T09:00', 1, None, '2024-01-04T08:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until east offset',
['2024-01-01T09:00', 1, None, '2024-01-03T07:00Z', 120],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], [])],
[('date until evening event',
['2024-01-01T20:00', 1, None, '2024-01-03', 60],
['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00']),
('local until exact',
['2024-01-01T09:00', 1, None, '2024-01-04T09:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00']),
('local until earlier time',
['2024-01-01T09:00', 1, None, '2024-01-04T08:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until east offset',
['2024-01-01T09:00', 1, None, '2024-01-03T07:00Z', 120],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], []),
('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], [])],
[('local until earlier time',
['2024-01-01T09:00', 1, None, '2024-01-04T08:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until east offset',
['2024-01-01T09:00', 1, None, '2024-01-03T07:00Z', 120],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], []),
('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], []),
('until before count reached',
['2024-01-01T09:00', 3, 10, '2024-01-08', 0],
['2024-01-01T09:00', '2024-01-04T09:00', '2024-01-07T09:00']),
('count before until reached',
['2024-03-01T18:30', 7, 2, '2024-12-31T00:00Z', 60],
['2024-03-01T18:30', '2024-03-08T18:30'])],
[('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], []),
('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], []),
('until before count reached',
['2024-01-01T09:00', 3, 10, '2024-01-08', 0],
['2024-01-01T09:00', '2024-01-04T09:00', '2024-01-07T09:00']),
('count before until reached',
['2024-03-01T18:30', 7, 2, '2024-12-31T00:00Z', 60],
['2024-03-01T18:30', '2024-03-08T18:30']),
('regression: count and until both set',
['2024-01-01T09:00', 1, 3, '2024-01-10', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('date until includes that day',
['2024-01-01T09:00', 2, None, '2024-01-07', 0],
['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00'])],
[('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], []),
('until before count reached',
['2024-01-01T09:00', 3, 10, '2024-01-08', 0],
['2024-01-01T09:00', '2024-01-04T09:00', '2024-01-07T09:00']),
('count before until reached',
['2024-03-01T18:30', 7, 2, '2024-12-31T00:00Z', 60],
['2024-03-01T18:30', '2024-03-08T18:30']),
('regression: count and until both set',
['2024-01-01T09:00', 1, 3, '2024-01-10', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('date until includes that day',
['2024-01-01T09:00', 2, None, '2024-01-07', 0],
['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00']),
('date until evening event',
['2024-01-01T20:00', 1, None, '2024-01-03', 60],
['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00']),
('local until exact',
['2024-01-01T09:00', 1, None, '2024-01-04T09:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00'])]]
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: count and until both set | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| date until includes that day | ['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00'] | ['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00'] | Passed |
| date until evening event | ['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00'] | ['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00'] | Passed |
| local until exact | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00'] | Passed |
| local until earlier time | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| utc until east offset | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| utc until west offset | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| count zero | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00', '2024-01-05T09:00', '2024-01-06T09:00', '2024-01-07T09:00', '2024-01-08T09:00', '2024-01-09T09:00', '2024-01-10T09:00', '2024-01-11T09:00', '2024-01-12T09:00', '2024-01-13T09:00', '2024-01-14T09:00', '2024-01-15T09:00', '2024-01-16T09:00', '2024-01-17T09:00', '2024-01-18T09:00', '2024-01-19T09:00', '2024-01-20T09:00', '2024-01-21T09:00', '2024-01-22T09:00', '2024-01-23T09:00', '2024-01-24T09:00', '2024-01-25T09:00', '2024-01-26T09:00', '2024-01-27T09:00', '2024-01-28T09:00', '2024-01-29T09:00', '2024-01-30T09:00', '2024-01-31T09:00', '2024-02-01T09:00', '2024-02-02T09:00', '2024-02-03T09:00', '2024-02-04T09:00', '2024-02-05T09:00', '2024-02-06T09:00', '2024-02-07T09:00', '2024-02-08T09:00', '2024-02-09T09:00'] | [] | Failed |
SHA-256 / dbc1b7e07d443a15f0f88752fa0da59e73f805cde1a2d668c0c57591423482b6
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, count, until, offset_min):
first = dt.datetime.fromisoformat(dtstart)
if until is None:
limit = None
elif until.endswith('Z'):
limit = dt.datetime.fromisoformat(until[:-1]) + dt.timedelta(minutes=offset_min)
elif len(until) == 10:
limit = dt.datetime.combine(dt.date.fromisoformat(until), dt.time(23, 59))
else:
limit = dt.datetime.fromisoformat(until)
out = []
for k in range(40):
t = first + dt.timedelta(days=k * interval)
if limit is not None and t > limit:
break
if count is not None and len(out) >= count:
break
out.append(t.isoformat(timespec='minutes'))
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: count and until both set',
['2024-01-01T09:00', 1, 3, '2024-01-10', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('date until includes that day',
['2024-01-01T09:00', 2, None, '2024-01-07', 0],
['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00']),
('date until evening event',
['2024-01-01T20:00', 1, None, '2024-01-03', 60],
['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00']),
('local until exact',
['2024-01-01T09:00', 1, None, '2024-01-04T09:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00']),
('local until earlier time',
['2024-01-01T09:00', 1, None, '2024-01-04T08:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until east offset',
['2024-01-01T09:00', 1, None, '2024-01-03T07:00Z', 120],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], [])],
[('date until evening event',
['2024-01-01T20:00', 1, None, '2024-01-03', 60],
['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00']),
('local until exact',
['2024-01-01T09:00', 1, None, '2024-01-04T09:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00']),
('local until earlier time',
['2024-01-01T09:00', 1, None, '2024-01-04T08:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until east offset',
['2024-01-01T09:00', 1, None, '2024-01-03T07:00Z', 120],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], []),
('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], [])],
[('local until earlier time',
['2024-01-01T09:00', 1, None, '2024-01-04T08:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until east offset',
['2024-01-01T09:00', 1, None, '2024-01-03T07:00Z', 120],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], []),
('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], []),
('until before count reached',
['2024-01-01T09:00', 3, 10, '2024-01-08', 0],
['2024-01-01T09:00', '2024-01-04T09:00', '2024-01-07T09:00']),
('count before until reached',
['2024-03-01T18:30', 7, 2, '2024-12-31T00:00Z', 60],
['2024-03-01T18:30', '2024-03-08T18:30'])],
[('utc until west offset',
['2024-01-01T09:00', 1, None, '2024-01-03T15:30Z', -300],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('count zero', ['2024-01-01T09:00', 1, 0, None, 0], []),
('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], []),
('until before count reached',
['2024-01-01T09:00', 3, 10, '2024-01-08', 0],
['2024-01-01T09:00', '2024-01-04T09:00', '2024-01-07T09:00']),
('count before until reached',
['2024-03-01T18:30', 7, 2, '2024-12-31T00:00Z', 60],
['2024-03-01T18:30', '2024-03-08T18:30']),
('regression: count and until both set',
['2024-01-01T09:00', 1, 3, '2024-01-10', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('date until includes that day',
['2024-01-01T09:00', 2, None, '2024-01-07', 0],
['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00'])],
[('count zero with until', ['2024-01-01T09:00', 1, 0, '2024-02-01', 0], []),
('until before count reached',
['2024-01-01T09:00', 3, 10, '2024-01-08', 0],
['2024-01-01T09:00', '2024-01-04T09:00', '2024-01-07T09:00']),
('count before until reached',
['2024-03-01T18:30', 7, 2, '2024-12-31T00:00Z', 60],
['2024-03-01T18:30', '2024-03-08T18:30']),
('regression: count and until both set',
['2024-01-01T09:00', 1, 3, '2024-01-10', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00']),
('date until includes that day',
['2024-01-01T09:00', 2, None, '2024-01-07', 0],
['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00']),
('date until evening event',
['2024-01-01T20:00', 1, None, '2024-01-03', 60],
['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00']),
('local until exact',
['2024-01-01T09:00', 1, None, '2024-01-04T09:00', 0],
['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00'])]]
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: count and until both set | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| date until includes that day | ['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00'] | ['2024-01-01T09:00', '2024-01-03T09:00', '2024-01-05T09:00', '2024-01-07T09:00'] | Passed |
| date until evening event | ['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00'] | ['2024-01-01T20:00', '2024-01-02T20:00', '2024-01-03T20:00'] | Passed |
| local until exact | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00', '2024-01-04T09:00'] | Passed |
| local until earlier time | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| utc until east offset | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| utc until west offset | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | ['2024-01-01T09:00', '2024-01-02T09:00', '2024-01-03T09:00'] | Passed |
| count zero | [] | [] | Passed |
SHA-256 / b09fd110f49ac53453900b1e1219edac8a59618dcb42706b116d1a4acb001d47
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.306607+00:00.
Case digest / fafa98be0103c53902f156be1792dc8fa1ff2600c1eb0a1efb939121e2d4fd0f