In continuation of my last blog post for managing Calendars dynamically for the ExtJs Calendar component, I present in this blog post the logic behind parsing and serializing Recurrence rules for the Calendar component, if you have enabled recurrence for the Calendar (You get to specify Recurrence rules for an event in the Calendar component, only if you enable recurrence for it, i.e. enableRecurrence=true).

For the record, the Calendar component Recurrence support is based on iCal RRULE (details of which are available here: http://www.kanzaki.com/docs/ical/rrule.html).

Here’s a sample Recurrence rule based on options selected in the Calendar Panel:

 

FREQ=MONTHLY;INTERVAL=3;BYMONTHDAY=20;COUNT=5

The above Recurrence rule is a iCal RRule produced by the Calendar Panel, which basically means that the Event recurrence is set to monthly, with the event recurring every 3 months (i.e. the event happens after a gap of 3 months), with the event occurring on 20th date of the appropriate month (i.e. 20th of every 3rd month), and the event recurs 5 times (i.e. it occurs for 5 times). You can see how an iCal RRULE can capture complex recurrence patterns in simple strings.

Parsing these recurrence strings is also not that involved as it looks on the onset. Here’s a quick overview of the general properties of the recurrence rule string.

  1. A null or empty recurrence rule means the event is a one-time non-recurring event.
  2. The various parts of the recurrence rule are joined with a semi-colon.
  3. Each part of the recurrence rule is a key/value pair separated by an equals sign.

Now follows a quick description of the common parts of the rrule recurrence string, and then I would discuss properties specific for the recurrence frequency (i.e. properties specific for daily, weekly, monthly or yearly recurrence patterns). I will discuss the properties in context of the ExtJs CalendarPanel and hence only the properties supported by the CalendarPanel would be discussed.

  1. FREQ: This specifies the recurrence frequency (i.e. how often an event recurs). Supported values are DAILY, WEEKLY, MONTHLY and YEARLY with obvious meanings. This is the only required property if an event is recurring, all other properties for the recurrence rule are optional.
  2. INTERVAL: Specifies the interval between 2 occurrences of the event. e.g. FREQ=DAILY and INTERVAL=5 means that the event occurs every 5th day.
    A very important point to note is that if user selected an Interval of 1 (for any frequency), this Interval attribute would be absent from the Recurrence string. So, you can safely assume a default of 1 if Interval is absent from the string.
  3.  COUNT: The number of times the event recurs.
    e.g. FREQ=WEEKLY;INTERVAL=2;COUNT=3 means the event recurs every second week for 3 times (i.e. in total 6 weeks but every second week).
  4.  UNTIL: The end date for the event. The event recurs only until this date.
    Note that COUNT and UNTIL properties are mutually exclusive. Only one of them can be specified  (which makes sense, COUNT means the event occurs this many times, UNTIL means the event recurs until this date).

Now we have properties specific for each FREQ type.

  1. DAILY
    This frequency does not have any specific property and only supports the above properties common for all frequency types.
  2. WEEKLY
    1. BYDAY: This property specifies the days of the week the event should recur.
      e.g. FREQ=WEEKLY;INTERVAL=3;BYDAY=MO,WE;COUNT=5 means that the event recurs every 3rd week on Monday and Wednesday and it has 5 recurrences spanning over 15 weeks (notice the interval is 3 meaning every 3rd week, so the total span is 15 weeks for COUNT=5).
      If BYDAY is absent for a WEEKLY frequency, you can interpret that to mean for all days of the week. If specified, the value for this property for WEEKLY frequency would be a comma-separated list of first 2 characters for a week day corresponding to the days chosen on the UI.
  3. MONTHLY
    For this frequency, you can choose if the event recurs on a fixed day of the month or a specified day of the specified week of the month. Accordingly, you have 2 mutually exclusive properties for this frequency.
    1. BYMONTHDAY: This property means that the event recurs on a fixed day of the month.
      e.g. FREQ=MONTHLY;INTERVAL=4;BYMONTHDAY=20;COUNT=5 means that the event recurs every 4 months, on 20th of each month and recurring for 5 times (spanning over 20 months).
    2. BYDAY: This property means that he event recurs on a fixed day of the fixed week of the month.
      e.g. FREQ=MONTHLY;INTERVAL=4;BYDAY=3MO;COUNT=5 means that the event recurs on 3rd Monday of every 4th month for 5 times.
      Notice BYDAY here contains 2 parts, the first being the week of the month (between 1 and 5), and the second the day of the week (first 2 characters of the week day).
  4. YEARLY
    This frequency recurrence rule is a bit confusing containing a required and an optional property.
    The required property is BYMONTH (containing the index of the month) and the optional is BYDAY. The interpretation of BYMONTH can vary slightly by the absence or presence of the BYDAY property. Let’s take an example first before discussing these 2 properties.

    i) FREQ=YEARLY;BYMONTH=12;COUNT=5
    means that the event occurs every year in the month of December (BYMONTH=12 implies the month of December). The date of the month is decided by the start date of the event. If the event start date is 12th December, then the above rule means that the event occurs on 12th December of each year for 5 years.

    ii) FREQ=YEARLY;BYMONTH=12;BYDAY=3MO;COUNT=5
    means that the event occurs on 3rd Monday in the month of December each year for 5 years.

    Here’s a more official description of the above properties:

    1. BYMONTH: This property specifies the month of the year (between 1 and 12). IF BYDAY is absent, then the day of the month is decided by the start date of the event in the specified month.
    2. BYDAY: This property means that the event recurs in the fixed day of the fixed week of the month specified by BYMONTH property. It again consists of 2 parts week of the month and day of the week (e.g. 3MO meaning 3rd Monday).
      As another example, BYMONTH=5;BYDAY=2TU means the event recurs on 2nd Tueday of the month of May.

I know that above can be a bit perplexing at first, but if you take each frequency one by one, and write code for parsing the recurrence string for a frequency independently, it all becomes easy.

You can use the above description to also create the RRULE recurrence string from the description of a recurrence specified by the user through the UI of your application.

I myself have code for parsing iCal RRULE strings to Microsoft Exchange Managed API Recurrence objects, and vice versa (i.e. serializing an Exchange Managed API Recurrence object as a recurrence rule string). However, the code is non-public and hence cannot be shared.

Nevertheless, the above description should be enough for parsing and serializing iCal recurrence rules in any platform and to any server-side representation. Please let me know if you face an issue (I cannot provide the code, but can certainly advice if needed).