Expand an RRULE or 5-field cron into concrete occurrences with DST handling, exclusions and conflict detection
Expands an RFC 5545 RRULE (FREQ DAILY/WEEKLY/MONTHLY/YEARLY, INTERVAL, COUNT, UNTIL, BYDAY with ordinals, BYMONTHDAY, BYMONTH, BYSETPOS, WKST; DTSTART with TZID; EXDATE) or a crontab(5) expression into up to 366 occurrences in a time zone, with the UTC instant of each, DST gap or overlap flags, caller blackout dates, a plain-English reading, and optionally the occurrences where it collides with a second rule. COUNT is applied before EXDATE removal, invalid dates (Feb 30) are skipped, a time in a gap is read with the pre-gap offset and an overlap uses its first occurrence (RFC 5545 3.3.5). Hourly/minutely FREQ, BYHOUR, BYYEARDAY, BYWEEKNO, RDATE, EXRULE, Quartz cron extensions and @macros return `unsupported`. Never reads the clock: the window starts at `from` (or DTSTART).
What you get
Whether a standup, report or billing job fires on the 5th Monday, on a gap day or twice on a fall-back night is decided here instead of guessed.
Call it
Send the JSON body below to https://agents.writerslogic.com/api/v1/recurrence-expand. An unpaid request answers 402 with the price and how to pay; a request that fails with a 5xx status is not charged.
curl -i -X POST https://agents.writerslogic.com/api/v1/recurrence-expand \
-H 'content-type: application/json' \
-d '{"kind":"rrule","rule":"DTSTART;TZID=America/New_York:19970902T090000\nRRULE:FREQ=DAILY;COUNT=10","limit":10}'
Input
| Field | Type | Required | Description |
|---|---|---|---|
kind | string; one of "rrule", "cron" | yes | |
rule | string; length 0..800 | yes | rrule: 'DTSTART;TZID=America/New_York:19970902T090000\nRRULE:FREQ=DAILY;COUNT=10\nEXDATE;TZID=America/New_York:19970903T090000' or just 'FREQ=...' with dtstart. cron: '*/15 9-17 * * 1-5' (dom and dow both restricted match if either does). |
dtstart | string; length 0..30 | no | Local DTSTART when the rule text has none. |
timeZone | string; length 0..64 | no | IANA zone for local times (required for cron; for rrule unless DTSTART has TZID or Z). |
from | string; length 0..30 | no | Local start of the output window; required for cron, default DTSTART for rrule. |
to | string; length 0..30 | no | Local end of the window, inclusive. |
limit | integer; 1..366 | no | Maximum occurrences returned (default 20). |
exdates | array<string; length 0..30>; max 200 items | no | Extra excluded local date-times (YYYY-MM-DDTHH:MM[:SS]) or dates (YYYY-MM-DD, excludes that day). |
blackouts | array<object>; max 50 items | no | Inclusive local date ranges to drop (holidays, freezes). |
durationMinutes | integer; 0..43200 | no | Occurrence length, for conflict overlap. |
other | object | no | A second rule to compare; conflicts are occurrences whose intervals overlap (equal instants when both durations are 0). |
Example request body
{
"kind": "rrule",
"rule": "DTSTART;TZID=America/New_York:19970902T090000\nRRULE:FREQ=DAILY;COUNT=10",
"limit": 10
}
Result
The response is { "data": ..., "_provenance": ... }. data carries these fields; _provenance is a signed W3C Verifiable Credential with a C2PA-style manifest, checked free at POST /api/v1/verify-provenance.
| Field | Type | Required | Description |
|---|---|---|---|
status | string; one of "pass", "fail", "unknown", "unsupported" | no | pass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass. |
occurrences | array<object> | no | |
count | integer | no | |
description | string | no | |
timeZone | string | no | |
excluded | array<object> | no | |
moreAvailable | boolean | no | |
scanCapped | boolean | no | |
conflicts | array<object> | no | |
comparedThroughUtc | string | no | |
reason | string | no | |
witnesses | array<object> | no | |
versions | object | no | Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile). |
limits | array<string> | no | |
deterministic | boolean | no | Always true: pure code, no model. |
Pay and connect
Available through: x402 (USDC on Base), MCP. MCP clients reach it through the calendar-deadline-kit package.
Machine-readable
- This agent as JSON (schemas, example, OpenAPI operation)
- Free signed sample response
- OpenAPI 3.1 · Catalog · Index of every agent