Recurrence rules allow events to recur, for example for a weekly meeting, or
an anniversary. This is done with the
RDATE property. The
property allows for a LOT of different rules. VObject has support for a lot of
them, but not all.
To read more about
RRULE and all the options, check out RFC5545.
VObject supports the following options:
UNTILfor an end date,
INTERVALfor for example "every 2 days",
COUNTto stop recurring after x items,
FREQ=DAILYto recur every day, and
BYDAYto limit it to certain days,
FREQ=WEEKLYto recur every week,
BYDAYto expand this to multiple weekdays in every week and
WKSTto specify on which day the week starts,
FREQ=MONTHLYto recur every month,
BYMONTHDAYto expand this to certain days in a month,
BYDAYto expand it to certain weekdays occuring in a month, and
BYSETPOSto limit the last two expansions,
FREQ=YEARLYto recur every year,
BYMONTHto expand that to certain months in a year, and
BYWEEKDAYto expand the
BYMONTHrule even further.
VObject supports the
EXDATE property for exclusions, and
RDATE as well.
This is an example of a meeting that happens every 2nd monday of every month:
BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Sabre//Sabre VObject 2.0//EN BEGIN:VEVENT UID:1102c450-e0d7-11e1-9b23-0800200c9a66 DTSTART:20120109T140000Z RRULE:FREQ=MONTHLY;BYDAY=MO;BYSETPOS=2 END:VEVENT END:VCALENDAR
To figure out all the meetings for this year, we can use the following syntax:
$vcalendar = VObject\Reader::read($data); $newVCalendar = $vcalendar->expand(new DateTime('2012-01-01'), new DateTime('2012-12-31'));
What the expand method does, is look at its inner events, and expand all the recurrence rules. Then, it returns a new calendar that has all its events expanded.
This new calendar now contains 12 events. The first will have its RRULE stripped,
and every subsequent VEVENT has the correct meeting date and a
This results in something like this:
BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Sabre//Sabre VObject 2.0//EN BEGIN:VEVENT UID:1102c450-e0d7-11e1-9b23-0800200c9a66 DTSTART:20120109T140000Z END:VEVENT BEGIN:VEVENT UID:1102c450-e0d7-11e1-9b23-0800200c9a66 RECURRENCE-ID:20120213T140000Z DTSTART:20120213T140000Z END:VEVENT BEGIN:VEVENT UID:1102c450-e0d7-11e1-9b23-0800200c9a66 RECURRENCE-ID:20120312T140000Z DTSTART:20120312T140000Z END:VEVENT ..etc.. END:VCALENDAR
In a recurring event, single instances can also be overriden. VObject also takes these into consideration. The reason we needed to specify a start and end-date, is because some recurrence rules can be 'never ending'.
You should make sure you pick a sane date-range. Because if you pick a 50 year time-range, for a daily recurring event; this would result in over 18K objects.
Note: Before sabre/vobject version 4, the
expand()method did not return a new calendar, but it edited the entire calendar in-place. So from version 4 to retrieve a calendar with only those events in the given period, you have to use the object returning from
$vcalendar = $vcalendar->expand(new DateTime('2012-01-01'), new DateTime('2012-12-31'));).