iCalendar recurrence expansion with time-zone transitions, exceptions and overrides
Exact prompt
# Calendar (iCalendar subset) recurrence expansion `input.json` names `calendar.ics` and gives `timezones` (each with `initial_offset_min` and `transitions` [[UTC instant, new offset minutes], ...]; offset = local minus UTC) and a UTC window `window_start`..`window_end`. Write `solve.py` (Python 3 standard library only); `python solve.py input.json answer.json`. Fresh calendars are generated. Everything you need is below. ## Parsing 1. Lines end in CRLF (accept LF too). A line starting with a space or tab continues the previous line (drop the line break and that one character). Blank lines are ignored. 2. Content line: `NAME *(;PARAM=value) : value`. Names and parameter names are case-insensitive. Parameter values may be double-quoted (quotes removed; `;` and `:` inside quotes are literal). The value starts after the first `:` that is not inside quotes. 3. Only `VEVENT` components count (`events_parsed` = number of VEVENT blocks, overrides included). Nested components (e.g. `VALARM`) inside a VEVENT are skipped entirely, properties included. For repeated properties, the first wins, except that `EXDATE` and `RDATE` accumulate (comma lists allowed). 4. Text unescaping (SUMMARY): `\\` -> `\`, `\;` -> `;`, `\,` -> `,`, `\n` or `\N` -> newline. 5. Date-times: `YYYYMMDDTHHMMSSZ` is UTC; `YYYYMMDDTHHMMSS` with `TZID=` is local time in that zone (no TZID: treat as UTC); `VALUE=DATE` or an 8-digit value is an all-day date. 6. Local -> UTC: find each interval of the zone's offset table whose offset o makes local - o fall inside that interval. If several do (repeated hour), take the earliest UTC instant. If none do (skipped hour), use local - (offset in force before that transition). 7. Length: `DTEND` - `DTSTART` (both converted to UTC; dates for all-day), or `DURATION` (`P[nW][nD][T[nH][nM][nS]]`), else 0 for timed events and 1 day for all-day ones. ## Recurrence (RRULE: FREQ, INTERVAL, COUNT, UNTIL, BYDAY, BYMONTHDAY, BYMONTH) 8. Expand in **local wall time** (the DTSTART's zone) and keep DTSTART's time of day; convert each occurrence to UTC with rule 6. 9. DAILY: every INTERVAL days; BYMONTH, BYMONTHDAY and BYDAY filter. WEEKLY: weeks start Monday; every INTERVAL weeks from DTSTART's week; BYDAY lists the days (default: DTSTART's weekday); BYMONTH/BYMONTHDAY filter. MONTHLY: every INTERVAL months; days = BYMONTHDAY (negative counts from month end; days that don't exist are skipped) and/or BYDAY (`MO` = every Monday, `2TU` = second Tuesday, `-1FR` = last Friday). If both are given, take the intersection; if neither, use DTSTART's day of month (skip months without it). YEARLY: every INTERVAL years; months = BYMONTH (default DTSTART's month), with days chosen as in MONTHLY. 10. Candidates before DTSTART are dropped; DTSTART itself is an occurrence only if it matches the rule. Occurrences are generated in time order. COUNT counts generated occurrences **before** EXDATE removal. UNTIL is inclusive and compared in UTC (a date-only UNTIL on a timed event means 23:59:59 UTC that day; on all-day events compare dates). 11. Add RDATEs, then remove EXDATEs (matched as UTC instants or dates). 12. Overrides: a VEVENT with `RECURRENCE-ID` and the same UID replaces the occurrence whose UTC start equals it: it uses its own DTSTART, length and SUMMARY, and has `override: true`. `STATUS:CANCELLED` removes that occurrence. 13. An event without RRULE has one occurrence (plus RDATEs). ## Output Occurrences overlapping the window: timed events with start < window_end and end > window_start (zero-length: start in [window_start, window_end)); all-day events compare dates the same way. Each is `{"uid", "summary", "start", "end", "all_day", "override"}` with `YYYY-MM-DDTHH:MM:SSZ` (UTC) or `YYYY-MM-DD` (all-day). Sort by start (all-day dates count as 00:00:00Z), then uid. `answer.json`: `{"occurrences": [...], "count": n, "events_parsed": n}` ## Scoring Hidden checks (partial credit; all must pass; exact): `unfold_unescape_parse`, `weekly_tz_exdate_override`, `monthly_byday_bymonthday`, `all_day_and_yearly`, `daily_until_rdate_cancel`, `dst_gap_overlap_zero_length`, `full_sorted_list` on the given calendar; `fresh_run_1`, `fresh_run_2`. Per-family checks compare the occurrences whose summary starts with that family's text, in order. 30-second limit per run.
Wall-clock expansion across DST with skipped and repeated hours, COUNT before EXDATE, negative BYMONTHDAY and -1FR, inclusive UNTIL, and overrides keyed on UTC RECURRENCE-ID. Original benchmark task written for usecaserank.com (not based on a specific public post). Headless, offline run on a reproducible fixture. Each run's notes say how its cost was measured (estimates are marked).
Success criteria: 1. unfold_unescape_parse 2. weekly_tz_exdate_override 3. monthly_byday_bymonthday 4. all_day_and_yearly 5. daily_until_rdate_cancel 6. dst_gap_overlap_zero_length 7. full_sorted_list 8. fresh_run_1 9. fresh_run_2
Best model for this task so far: GPT-6.1 Sol (effort default (no reasoning-effort override) · thinking on) (success, $0.11, 2m).
All runs (4)
75% pass rate across 4 eligible runs: 3 pass, 1 partial, 0 fail. Partial and failed runs are listed below with everything else.ⓘ
| Model | Cost | Time | Step-insⓘ | Autonomy | Outcome | Trustⓘ | Date | Compare |
|---|---|---|---|---|---|---|---|---|
| OGPT-6.1 Soldefault · thinking on | $0.11 | 2m | 0 | Fully autonomous | pass | Trust 80% | 2026-10-22 | |
| AClaude Haiku 5.5default · thinking on | $0.05 | 4m | 0 | Fully autonomous | partial | Trust 80% | 2026-10-20 | |
| AClaude Opus 5.5default · thinking on | $0.42 | 2m | 0 | Fully autonomous | pass | Trust 80% | 2026-10-20 | |
| AClaude Sonnet 5.5default · thinking on | $0.16 | 48s | 0 | Fully autonomous | pass | Trust 80% | 2026-10-20 |
Embed this result
A live badge for this use case. It links back here and updates as new runs are published.
Get new runs and ranking changes weekly
Which models got better or cheaper on real tasks like this one.