Thank you for being patient! We're working hard on resolving the issue
The recurrence layer parses iCalendar recurrence strings, preserves exclusion dates, generates matching dates, and models Google Calendar compatibility where Google behavior differs from plain RFC 5545.
RRule parses and serializes RRULE: lines.ExDate parses EXDATE lines and stores excluded dates.ICalendar.Raw parses recurrence arrays into structured lines.Recurrence wraps parsed iCalendar data and generates dates.GoogleEventGenerator emits DateTime<Utc> events with Google Calendar's
timezone behavior.import { Recurrence, naivedate } from "@tento-chrono";
const recurrence = await Recurrence.parse([
"RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR;COUNT=10",
"EXDATE:20260429",
]);
const parsed = recurrence.exp();
RRule.parseWithRecurrence() is useful when only the rule and exclusion dates
are needed. Recurrence.parse() is the higher-level entry point for generation.
generate() yields matching YearMonthDay values with an optional start date
and limit.
generateToDate() yields until an exclusive end date and can enable Google
Calendar behavior.
const dates = parsed.generateToDate(
naivedate(2026, 4, 1),
naivedate(2026, 5, 1),
);
When a recurrence has a TZID, recurrence.timezone() resolves the matching
TimezoneRegion.
Google Calendar preserves local wall-clock time across DST transitions. That means a weekly 10:00 event remains 10:00 local time even when its UTC timestamp changes after a DST boundary.
Google also treats UNTIL differently based on shape:
UNTIL values are exclusive of that whole date;UNTIL values are inclusive up to the exact instant.Use GoogleEventGenerator when comparing against Google Calendar API results or
generating events imported from Google. The tests under
tests/google_recurrence_test_data/ document edge cases for BYDAY, BYMONTHDAY,
BYWEEKNO, EXDATE, DST transitions, and timezone mismatches.
RRule.toReadableDisplay() produces human-facing summaries for common rules,
such as:
Daily, 5 timesWeekly on Monday, Wednesday and FridayMonthly on the 2nd Tuesday, 6 timesUse it for lightweight labels, not as a replacement for the structured rule.