Recurring Events

Repeat an event daily, weekly, monthly or yearly with a practical subset of the iCalendar RRULE grammar — as a string or a typed object. The event’s start acts as DTSTART; occurrences inherit its time and duration.

// String form (RFC 5545 RRULE subset)…
recurrence: 'FREQ=WEEKLY;BYDAY=MO,WE,FR;COUNT=10'

// …or the equivalent object form
recurrence: {
  freq: 'weekly',      // 'daily' | 'weekly' | 'monthly' | 'yearly'
  interval: 1,         // every N periods
  byDay: [1, 3, 5],    // 0 = Sunday … 6 = Saturday
  count: 10            // or: until: new Date(2027, 0, 1)
}

// Cancel individual occurrences by date:
exdates: [new Date(2026, 7, 19)]
Five recurring patterns

September 2026

Sun
Mon
Tue
Wed
Thu
Fri
Sat
30
31
Sep 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Oct 1
2
3

Supported rule parts

RRULEObject formMeaning
FREQ=DAILY|WEEKLY|MONTHLY|YEARLYfreqBase frequency (required).
INTERVAL=2intervalEvery 2nd day/week/month/year.
COUNT=10countStop after 10 occurrences, counted from the event start.
UNTIL=20261231untilLast possible occurrence date (inclusive).
BYDAY=MO,WE,FRbyDay: [1,3,5]Weekly: which weekdays.
BYDAY=2TU / -1FRbyNthDayMonthly: the 2nd Tuesday / last Friday.
BYMONTHDAY=1,15byMonthDayMonthly: on these days of the month.
exdates: Date[]Skip occurrences on these days (cancelled instances).

Behavior details

  • Occurrences keep the wall-clock time of the original event across DST changes.
  • Monthly rules skip months where the day doesn’t exist (Jan 31 → no Feb 31), matching Google Calendar.
  • Yearly rules starting Feb 29 only fire in leap years.
  • Recurring instances show a ↻ mark. Dragging or resizing one opens a confirm popover with “This event” (detaches the occurrence) and “This and following” (splits the series at that point) — like Google Calendar.
  • The details popover offers “Delete this occurrence” (adds an exdate) and “Delete series”.
  • Expansion is windowed to the visible range and hard-capped at 1000 occurrences per event, so infinite rules are safe.
Editing a series — both “this event” and “this and following” edits are built in: onSeriesDetach / onSeriesSplit report the results, COUNT and exdates are re-partitioned automatically, and weekly BYDAY lists re-anchor when the drag changes the weekday. The pure helpers detachOccurrence, excludeOccurrence and splitSeries are exported for data-layer use.