FA-77086 / Calendar recurrence rules / Open access
Daily BYHOUR/BYMINUTE time-of-day expansion: hour normalization · case 01
BYHOUR=17,9 emits the evening slot before the morning slot and repeats duplicated hours.
ROOT CAUSE
The BYHOUR list is used as given, unsorted and with duplicates.
VERIFIED REPAIR
At the hour normalization decision use `sorted(set(byhour))`, leaving the other decision sites of the model unchanged.
Unsuccessful approach: The partial repair `sorted(byhour)` sorts but keeps duplicate hours, producing repeated instances.
Case contract
FREQ=DAILY. Each day produces the cartesian product of BYHOUR and BYMINUTE in chronological order; a missing BYHOUR defaults to the dtstart hour and a missing BYMINUTE to the dtstart minute. Duplicates in either list are ignored. Times before dtstart are dropped. Return the first count ISO 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, byhour, byminute, count):
first = dt.datetime.fromisoformat(dtstart)
hours = list(byhour) if byhour else [first.hour]
minutes = sorted(set(byminute)) if byminute else [first.minute]
out = []
for k in range(400):
day = first.date() + dt.timedelta(days=k)
for h, mi in [(h, mi) for h in hours for mi in minutes]:
t = dt.datetime.combine(day, dt.time(h, mi))
if t < first:
continue
if len(out) >= count:
return out
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: default minute from dtstart',
['2024-01-01T09:30', [9, 17], [], 4],
['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30']),
('only byminute',
['2024-01-01T14:10', [], [0, 30], 4],
['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15']),
('product of two lists',
['2024-01-01T00:00', [9, 13], [0, 45], 5],
['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00']),
('dtstart after some slots',
['2024-01-02T12:00', [8, 12, 18], [0], 4],
['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00']),
('dtstart between minutes',
['2024-01-02T12:20', [12], [0, 20, 40], 4],
['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20']),
('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05'])],
[('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15']),
('product of two lists',
['2024-01-01T00:00', [9, 13], [0, 45], 5],
['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00']),
('dtstart after some slots',
['2024-01-02T12:00', [8, 12, 18], [0], 4],
['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00']),
('dtstart between minutes',
['2024-01-02T12:20', [12], [0, 20, 40], 4],
['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20']),
('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05']),
('count zero', ['2024-01-01T09:00', [9], [0], 0], []),
('no lists',
['2024-02-28T23:45', [], [], 3],
['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45'])],
[('dtstart after some slots',
['2024-01-02T12:00', [8, 12, 18], [0], 4],
['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00']),
('dtstart between minutes',
['2024-01-02T12:20', [12], [0, 20, 40], 4],
['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20']),
('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05']),
('count zero', ['2024-01-01T09:00', [9], [0], 0], []),
('no lists', ['2024-02-28T23:45', [], [], 3], ['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45']),
('unsorted minutes',
['2024-02-28T07:00', [7, 8], [50, 10], 5],
['2024-02-28T07:10', '2024-02-28T07:50', '2024-02-28T08:10', '2024-02-28T08:50', '2024-02-29T07:10']),
('late hour only list',
['2024-05-05T22:15', [23, 1], [], 4],
['2024-05-05T23:15', '2024-05-06T01:15', '2024-05-06T23:15', '2024-05-07T01:15']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'])],
[('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05']),
('count zero', ['2024-01-01T09:00', [9], [0], 0], []),
('no lists', ['2024-02-28T23:45', [], [], 3], ['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45']),
('unsorted minutes',
['2024-02-28T07:00', [7, 8], [50, 10], 5],
['2024-02-28T07:10', '2024-02-28T07:50', '2024-02-28T08:10', '2024-02-28T08:50', '2024-02-29T07:10']),
('late hour only list',
['2024-05-05T22:15', [23, 1], [], 4],
['2024-05-05T23:15', '2024-05-06T01:15', '2024-05-06T23:15', '2024-05-07T01:15']),
('regression: default minute from dtstart',
['2024-01-01T09:30', [9, 17], [], 4],
['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30']),
('only byminute',
['2024-01-01T14:10', [], [0, 30], 4],
['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'])],
[('no lists', ['2024-02-28T23:45', [], [], 3], ['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45']),
('unsorted minutes',
['2024-02-28T07:00', [7, 8], [50, 10], 5],
['2024-02-28T07:10', '2024-02-28T07:50', '2024-02-28T08:10', '2024-02-28T08:50', '2024-02-29T07:10']),
('late hour only list',
['2024-05-05T22:15', [23, 1], [], 4],
['2024-05-05T23:15', '2024-05-06T01:15', '2024-05-06T23:15', '2024-05-07T01:15']),
('regression: default minute from dtstart',
['2024-01-01T09:30', [9, 17], [], 4],
['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30']),
('only byminute',
['2024-01-01T14:10', [], [0, 30], 4],
['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15']),
('product of two lists',
['2024-01-01T00:00', [9, 13], [0, 45], 5],
['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09: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: default minute from dtstart | ['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30'] | ['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30'] | Passed |
| only byminute | ['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00'] | ['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00'] | Passed |
| unsorted duplicate hours | ['2024-01-01T17:15', '2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T17:15'] | ['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'] | Failed |
| product of two lists | ['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00'] | ['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00'] | Passed |
| dtstart after some slots | ['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00'] | ['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00'] | Passed |
| dtstart between minutes | ['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20'] | ['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20'] | Passed |
| three by three | ['2024-03-10T06:05', '2024-03-10T06:10', '2024-03-10T06:50', '2024-03-10T12:05', '2024-03-10T12:10', '2024-03-10T12:50', '2024-03-10T18:05'] | ['2024-03-10T06:05', '2024-03-10T06:10', '2024-03-10T06:50', '2024-03-10T12:05', '2024-03-10T12:10', '2024-03-10T12:50', '2024-03-10T18:05'] | Passed |
SHA-256 / 11be287bca46c30255cd28f9130633bcc3ca977d6b720b233e6d9b7019725b35
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, byhour, byminute, count):
first = dt.datetime.fromisoformat(dtstart)
hours = sorted(byhour) if byhour else [first.hour]
minutes = sorted(set(byminute)) if byminute else [first.minute]
out = []
for k in range(400):
day = first.date() + dt.timedelta(days=k)
for h, mi in [(h, mi) for h in hours for mi in minutes]:
t = dt.datetime.combine(day, dt.time(h, mi))
if t < first:
continue
if len(out) >= count:
return out
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: default minute from dtstart',
['2024-01-01T09:30', [9, 17], [], 4],
['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30']),
('only byminute',
['2024-01-01T14:10', [], [0, 30], 4],
['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15']),
('product of two lists',
['2024-01-01T00:00', [9, 13], [0, 45], 5],
['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00']),
('dtstart after some slots',
['2024-01-02T12:00', [8, 12, 18], [0], 4],
['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00']),
('dtstart between minutes',
['2024-01-02T12:20', [12], [0, 20, 40], 4],
['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20']),
('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05'])],
[('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15']),
('product of two lists',
['2024-01-01T00:00', [9, 13], [0, 45], 5],
['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00']),
('dtstart after some slots',
['2024-01-02T12:00', [8, 12, 18], [0], 4],
['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00']),
('dtstart between minutes',
['2024-01-02T12:20', [12], [0, 20, 40], 4],
['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20']),
('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05']),
('count zero', ['2024-01-01T09:00', [9], [0], 0], []),
('no lists',
['2024-02-28T23:45', [], [], 3],
['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45'])],
[('dtstart after some slots',
['2024-01-02T12:00', [8, 12, 18], [0], 4],
['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00']),
('dtstart between minutes',
['2024-01-02T12:20', [12], [0, 20, 40], 4],
['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20']),
('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05']),
('count zero', ['2024-01-01T09:00', [9], [0], 0], []),
('no lists', ['2024-02-28T23:45', [], [], 3], ['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45']),
('unsorted minutes',
['2024-02-28T07:00', [7, 8], [50, 10], 5],
['2024-02-28T07:10', '2024-02-28T07:50', '2024-02-28T08:10', '2024-02-28T08:50', '2024-02-29T07:10']),
('late hour only list',
['2024-05-05T22:15', [23, 1], [], 4],
['2024-05-05T23:15', '2024-05-06T01:15', '2024-05-06T23:15', '2024-05-07T01:15']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'])],
[('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05']),
('count zero', ['2024-01-01T09:00', [9], [0], 0], []),
('no lists', ['2024-02-28T23:45', [], [], 3], ['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45']),
('unsorted minutes',
['2024-02-28T07:00', [7, 8], [50, 10], 5],
['2024-02-28T07:10', '2024-02-28T07:50', '2024-02-28T08:10', '2024-02-28T08:50', '2024-02-29T07:10']),
('late hour only list',
['2024-05-05T22:15', [23, 1], [], 4],
['2024-05-05T23:15', '2024-05-06T01:15', '2024-05-06T23:15', '2024-05-07T01:15']),
('regression: default minute from dtstart',
['2024-01-01T09:30', [9, 17], [], 4],
['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30']),
('only byminute',
['2024-01-01T14:10', [], [0, 30], 4],
['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'])],
[('no lists', ['2024-02-28T23:45', [], [], 3], ['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45']),
('unsorted minutes',
['2024-02-28T07:00', [7, 8], [50, 10], 5],
['2024-02-28T07:10', '2024-02-28T07:50', '2024-02-28T08:10', '2024-02-28T08:50', '2024-02-29T07:10']),
('late hour only list',
['2024-05-05T22:15', [23, 1], [], 4],
['2024-05-05T23:15', '2024-05-06T01:15', '2024-05-06T23:15', '2024-05-07T01:15']),
('regression: default minute from dtstart',
['2024-01-01T09:30', [9, 17], [], 4],
['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30']),
('only byminute',
['2024-01-01T14:10', [], [0, 30], 4],
['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15']),
('product of two lists',
['2024-01-01T00:00', [9, 13], [0, 45], 5],
['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09: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: default minute from dtstart | ['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30'] | ['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30'] | Passed |
| only byminute | ['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00'] | ['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00'] | Passed |
| unsorted duplicate hours | ['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-01T17:15', '2024-01-02T09:15'] | ['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'] | Failed |
| product of two lists | ['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00'] | ['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00'] | Passed |
| dtstart after some slots | ['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00'] | ['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00'] | Passed |
| dtstart between minutes | ['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20'] | ['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20'] | Passed |
| three by three | ['2024-03-10T06:05', '2024-03-10T06:10', '2024-03-10T06:50', '2024-03-10T12:05', '2024-03-10T12:10', '2024-03-10T12:50', '2024-03-10T18:05'] | ['2024-03-10T06:05', '2024-03-10T06:10', '2024-03-10T06:50', '2024-03-10T12:05', '2024-03-10T12:10', '2024-03-10T12:50', '2024-03-10T18:05'] | Passed |
SHA-256 / ea518baea2606db2b8fe8f83c4f83f499beb9f717dc5484ec271a84fc892c653
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, byhour, byminute, count):
first = dt.datetime.fromisoformat(dtstart)
hours = sorted(set(byhour)) if byhour else [first.hour]
minutes = sorted(set(byminute)) if byminute else [first.minute]
out = []
for k in range(400):
day = first.date() + dt.timedelta(days=k)
for h, mi in [(h, mi) for h in hours for mi in minutes]:
t = dt.datetime.combine(day, dt.time(h, mi))
if t < first:
continue
if len(out) >= count:
return out
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: default minute from dtstart',
['2024-01-01T09:30', [9, 17], [], 4],
['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30']),
('only byminute',
['2024-01-01T14:10', [], [0, 30], 4],
['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15']),
('product of two lists',
['2024-01-01T00:00', [9, 13], [0, 45], 5],
['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00']),
('dtstart after some slots',
['2024-01-02T12:00', [8, 12, 18], [0], 4],
['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00']),
('dtstart between minutes',
['2024-01-02T12:20', [12], [0, 20, 40], 4],
['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20']),
('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05'])],
[('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15']),
('product of two lists',
['2024-01-01T00:00', [9, 13], [0, 45], 5],
['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00']),
('dtstart after some slots',
['2024-01-02T12:00', [8, 12, 18], [0], 4],
['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00']),
('dtstart between minutes',
['2024-01-02T12:20', [12], [0, 20, 40], 4],
['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20']),
('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05']),
('count zero', ['2024-01-01T09:00', [9], [0], 0], []),
('no lists',
['2024-02-28T23:45', [], [], 3],
['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45'])],
[('dtstart after some slots',
['2024-01-02T12:00', [8, 12, 18], [0], 4],
['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00']),
('dtstart between minutes',
['2024-01-02T12:20', [12], [0, 20, 40], 4],
['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20']),
('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05']),
('count zero', ['2024-01-01T09:00', [9], [0], 0], []),
('no lists', ['2024-02-28T23:45', [], [], 3], ['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45']),
('unsorted minutes',
['2024-02-28T07:00', [7, 8], [50, 10], 5],
['2024-02-28T07:10', '2024-02-28T07:50', '2024-02-28T08:10', '2024-02-28T08:50', '2024-02-29T07:10']),
('late hour only list',
['2024-05-05T22:15', [23, 1], [], 4],
['2024-05-05T23:15', '2024-05-06T01:15', '2024-05-06T23:15', '2024-05-07T01:15']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'])],
[('three by three',
['2024-03-10T00:00', [6, 12, 18], [5, 10, 50], 7],
['2024-03-10T06:05',
'2024-03-10T06:10',
'2024-03-10T06:50',
'2024-03-10T12:05',
'2024-03-10T12:10',
'2024-03-10T12:50',
'2024-03-10T18:05']),
('count zero', ['2024-01-01T09:00', [9], [0], 0], []),
('no lists', ['2024-02-28T23:45', [], [], 3], ['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45']),
('unsorted minutes',
['2024-02-28T07:00', [7, 8], [50, 10], 5],
['2024-02-28T07:10', '2024-02-28T07:50', '2024-02-28T08:10', '2024-02-28T08:50', '2024-02-29T07:10']),
('late hour only list',
['2024-05-05T22:15', [23, 1], [], 4],
['2024-05-05T23:15', '2024-05-06T01:15', '2024-05-06T23:15', '2024-05-07T01:15']),
('regression: default minute from dtstart',
['2024-01-01T09:30', [9, 17], [], 4],
['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30']),
('only byminute',
['2024-01-01T14:10', [], [0, 30], 4],
['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'])],
[('no lists', ['2024-02-28T23:45', [], [], 3], ['2024-02-28T23:45', '2024-02-29T23:45', '2024-03-01T23:45']),
('unsorted minutes',
['2024-02-28T07:00', [7, 8], [50, 10], 5],
['2024-02-28T07:10', '2024-02-28T07:50', '2024-02-28T08:10', '2024-02-28T08:50', '2024-02-29T07:10']),
('late hour only list',
['2024-05-05T22:15', [23, 1], [], 4],
['2024-05-05T23:15', '2024-05-06T01:15', '2024-05-06T23:15', '2024-05-07T01:15']),
('regression: default minute from dtstart',
['2024-01-01T09:30', [9, 17], [], 4],
['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30']),
('only byminute',
['2024-01-01T14:10', [], [0, 30], 4],
['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00']),
('unsorted duplicate hours',
['2024-01-01T08:00', [17, 9, 17], [15], 4],
['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15']),
('product of two lists',
['2024-01-01T00:00', [9, 13], [0, 45], 5],
['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09: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: default minute from dtstart | ['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30'] | ['2024-01-01T09:30', '2024-01-01T17:30', '2024-01-02T09:30', '2024-01-02T17:30'] | Passed |
| only byminute | ['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00'] | ['2024-01-01T14:30', '2024-01-02T14:00', '2024-01-02T14:30', '2024-01-03T14:00'] | Passed |
| unsorted duplicate hours | ['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'] | ['2024-01-01T09:15', '2024-01-01T17:15', '2024-01-02T09:15', '2024-01-02T17:15'] | Passed |
| product of two lists | ['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00'] | ['2024-01-01T09:00', '2024-01-01T09:45', '2024-01-01T13:00', '2024-01-01T13:45', '2024-01-02T09:00'] | Passed |
| dtstart after some slots | ['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00'] | ['2024-01-02T12:00', '2024-01-02T18:00', '2024-01-03T08:00', '2024-01-03T12:00'] | Passed |
| dtstart between minutes | ['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20'] | ['2024-01-02T12:20', '2024-01-02T12:40', '2024-01-03T12:00', '2024-01-03T12:20'] | Passed |
| three by three | ['2024-03-10T06:05', '2024-03-10T06:10', '2024-03-10T06:50', '2024-03-10T12:05', '2024-03-10T12:10', '2024-03-10T12:50', '2024-03-10T18:05'] | ['2024-03-10T06:05', '2024-03-10T06:10', '2024-03-10T06:50', '2024-03-10T12:05', '2024-03-10T12:10', '2024-03-10T12:50', '2024-03-10T18:05'] | Passed |
SHA-256 / 9f39fd235cc0fa4db8ace75edb2937cf2b9bfc2a4185372a25745116e4df9e93
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:22.329137+00:00.
Case digest / 7b6e6b92360cae8eca3046437d3ee65f1688267465913a182a59498b4ba292b7