iCalendar Recurrences

What is recurrence?

A recurring event is one that repeats at regular or irregular intervals. For example, a weekly lunch meeting, an anniversary, etc. These often occur in real life and thus need to be represented in digital calendars and iCalendar. Recurring events are often the source of interoperability problems with iCalendar, so deserve special attention.

PlantUML SVG diagram

In the real world, a recurrence pattern is typically based on common intervals of time (a day, a week, a month, a year, etc). Often times, a recurrence is not every week, but every other week, for example. So there needs to be a way to express an interval between each recurrence. Some types of recurrence never end - typically anniversaries, though often it is because no obvious end point can be identified. In other cases there is a well-known end point, determined either by the total number of recurrences (e.g., every day for the next three days), or a fixed end date (e.g., every week until the end of the month).

A number of more complex situations can arise, such as patterns tied to a specific day of the week within a month (e.g., the first Monday of each month), or an offset within the month (e.g., “pay day” - the last weekday of each month). All of these need to be represented in some fashion in a digital calendar.

Sometimes an event in a recurrence set needs to be removed (e.g., an every Monday pattern would produce an event that falls on a holiday, so that event needs to be cancelled). Alternatively, an event in a recurrence set mighty need to be rescheduled (e.g., due to a holiday, an event in an every Monday pattern is moved to Tuesday, rather than being cancelled). Such changes to the normal pattern of occurrence is called an exception.

Sometimes an irregular pattern exists - for example the Easter holiday is determined by a complex astronomical calculation that would not be trivial to represent in iCalendar. Or additional one-off meetings are scheduled (e.g., during one weekly meeting the participants agree to have a follow-up later in the week). To cope with these, it is possible to specify explicit dates for items in a recurrence set, rather than use a rule.

iCalendar’s Implementation of Recurrences

iCalendar supports recurrences by allowing rules, specific dates, specific exception dates, and overridden instances to all be specified using properties and components. The recurrence properties can only appear in the component defining the master instance of a recurrence set - they can never be used in components representing overridden instances. This means that if the recurrence pattern needs to change in a significant manner (e.g., switching from a weekly meeting to a monthly meeting) then two separate events are needed: one for the old set of events with the original recurrence pattern, and one for the new set with the new pattern.

The RRULE Property

Recurrence rules are defined via the RRULE property. The value of this property is a semicolon separated list of items describing various aspects of the recurrence pattern, such as the frequency (e.g., daily, weekly, monthly, yearly), the interval (e.g., every two weeks, or every fourth month), the total number of items the rule generates (e.g., repeat for five times), the point in time where the recurrence stops (e.g., repeat until the 4th of June).

Here are some simple examples:

  • RRULE:FREQ=YEARLY
    • An event that occurs once a year on a specific date. i.e., an anniversary.
  • RRULE:FREQ=DAILY;COUNT=3
    • An event that occurs every day for three days only.
  • RRULE:FREQ=WEEKLY;INTERVAL=2
    • An event that occurs every two weeks.
  • RRULE:FREQ=MONTHLY;BYMONTHDAY=-1
    • An event that occurs on the last day of every month.

An RRULE property can appear at most once in a calendar component. It is used only in the component that defines the master instance of a recurrence set (it can never be used in an overridden instance).

In order to determine a set of recurrences generated by a particular RRULE, a starting point is required. The starting point is defined by the value of the DTSTART property in the master component. For example, if DTSTART is set to the 4th of July of some year, and a yearly RRULE is specified, then the event occurs on the 4th of July of all years on or after the year specified in DTSTART. The RRULE itself might constrain what values are allowed for the DTSTART property - for example an RRULE that specifies a recurring event on the first Monday of every month, requires that the DTSTART of the master component falls on the first Monday of a month. i.e., the DTSTART of the master component must match the first instance of the recurrence pattern.

The full ics file for this example with three occurrences now looks like:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//ABC Corporation//NONSGML My Product//EN
BEGIN:VEVENT
SUMMARY:Lunchtime meeting
UID:ff808181-1fd7389e-011f-d7389ef9-00000003@example.com
DTSTART;TZID=America/New_York:20160420T120000
DURATION:PT1H
LOCATION:Mo's bar - back room
RRULE:FREQ=WEEKLY;COUNT=3
END:VEVENT
END:VCALENDAR

PlantUML SVG diagram

To fully understand all the possible variations of RRULE values, and possible patterns that can be generated, you need to read the iCalendar specification, in particular Sections 3.3.10 & 3.8.5.3

The RDATE and EXDATE Properties

The RDATE property is used to specify one-off instances in a recurrence set. This is useful for cases where a “regular” pattern cannot be defined, or one off “exceptions” to a regular pattern. e.g., a weekly occurring event needs one additional event in one particular week to follow-up on items discussed in the previous meeting. The value of the RDATE determines the start (and possibly duration) of the one-off instance. The recurrence instance specified by the RDATE can also be overridden if some other aspect of the event differs from the master component.

The EXDATE property is used to remove instances from a recurrence set defined by an RRULE. For example, a weekly meeting might occur on a public holiday, and thus won’t take place so needs to be removed from the recurrence set.

The full ics file for this example with three occurrences without the second one now looks like:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//ABC Corporation//NONSGML My Product//EN
BEGIN:VEVENT
SUMMARY:Lunchtime meeting
UID:ff808181-1fd7389e-011f-d7389ef9-00000003
DTSTART;TZID=America/New_York:20160420T120000
DURATION:PT1H
LOCATION:Mo's bar - back room
RRULE:FREQ=WEEKLY;COUNT=3
EXDATE;TZID=America/New_York:20160427T120000
END:VEVENT
END:VCALENDAR

PlantUML SVG diagram

There is also a RRule Generator tool on icalendar.org helping you to generate the needed syntax for daily, weekly and yearly rules.

Overridden Instances

An overridden instance is one where one or more properties from the event are changed. This may be because the organizer has explicitly changed the property, for example by updating the DESCRIPTION with a meeting agenda. It may also happen as a result of scheduling where the attendees PARTSTAT is stored in the overridden instance.

An override is stored as a COMPLETE copy of the master with the DTSTART and/or DTEND set to the dates for the instance and will contain a RECURRENCE-ID property to identify which instance it is. It MUST NOT contain any RRULE, RDATE or EXDATE properties.

This override mechanism is one of the problems with long running recurring events. If every instance is modified the event data becomes very large over time.

Was this page helpful for you? Please give us Feedback.