Calendar (.ics) File Structure

This article describes how iCalendar data is stored on a CalDAV server. To fond how to parse and generate iCalendar data read articles in the Using IT Hit Collab Library API section.

Event/To-do Components and Instances

Every calendar file stored on a CalDAV server contains a single iCalendar object with a single event or to-do defined inside it. Every event/to-do object consists of one or more event or to-do components. It also typically contains one or more time zone component.

Calendar file (.ics file) structure.

Recurring event/to-do expands to event/to-do instances. You can see event/to-do instances when calendar is displayed in your client application. Below is an iPhone Calendar application with a recurring event that has 4 instances Monday through Thursday:

Event instances

Note that it consists of a single event component. Below you can see this event in iCalendar format, you will find a single VEVENT definition in it:

BEGIN:VCALENDAR
…
BEGIN:VEVENT
CREATED:20151219T021727Z
DTEND;TZID=America/Toronto:20170515T110000
DTSTAMP:20151219T021727Z
DTSTART;TZID=America/Toronto:20170515T100000
LAST-MODIFIED:20151219T021727Z
RRULE:FREQ=DAILY;UNTIL=20170519T035959Z
SEQUENCE:0
SUMMARY:Meeting
TRANSP:OPAQUE
UID:21B97459-D97B-4B23-AF2A-E2759745C299
END:VEVENT
END:VCALENDAR

A non-recurring event or recurring event that does not have overridden instances consists of a single component. However when you update an event instance of a recurring event, more components are created, see below.

Do not confuse the VCALENDAR object that you will find inside a .ics file with actual calendar. The calendar is a calendar folder and is represented by ICalendarFolderAsync interface. Every calendar file (.ics file) on a CalDAV server stores a single event or to-do, even though the info about event/to-do is wrapped in “VCALENDAR” block. The .ics file is represented by ICalendarFileAsync interface. You can find more about calendar folders and calendar files in the Creating CalDAV Server article.

What Happens when You Update an Instance of a Recurring Event?

When you change a separate event instance in your CalDAV client application, for example when you update the time or summary for a particular day, the client submits to the server the updated iCalendar object with a new component added to the event. This new component contains information about updated event instance and has a RECURRENCE-ID property that stores date and time of the event instance. Here is the example of the above event with the last instance summary being changed to “Final Meeting” and start time being set to 11:00AM:

When you update an event instance a new event component is created.

Here is its representation in iCalendar format. Note the 2 VEVENT components stored in it – the first one contains a recurring event description and the second one - event instance that was overridden by the client ("Final Meeting").

BEGIN:VCALENDAR
…
BEGIN:VEVENT
CREATED:20151219T021727Z
DTEND;TZID=America/Toronto:20170515T110000
DTSTAMP:20151219T022011Z
DTSTART;TZID=America/Toronto:20170515T100000
LAST-MODIFIED:20151219T021727Z
RRULE:FREQ=DAILY;UNTIL=20170519T035959Z
SEQUENCE:0
SUMMARY:Meeting
TRANSP:OPAQUE
UID:21B97459-D97B-4B23-AF2A-E2759745C299
END:VEVENT
BEGIN:VEVENT
CREATED:20151219T022011Z
DTEND;TZID=America/Toronto:20170518T120000
DTSTAMP:20151219T022011Z
DTSTART;TZID=America/Toronto:20170518T110000
LAST-MODIFIED:20151219T022011Z
RECURRENCE-ID;TZID=America/Toronto:20170518T100000
SEQUENCE:0
SUMMARY:Final Meeting
TRANSP:OPAQUE
UID:21B97459-D97B-4B23-AF2A-E2759745C299
END:VEVENT
END:VCALENDAR

What Happens when You Delete a Recurring Event Instance?

When you delete the event instance, the client application will add an EXDATE property for every event instance that was deleted with date and time of the instance that should not occur. The EXDATE property is called exception dates and can contain more than one exception date as every EXDATE property value. Below you can see an example of the same event with 2 instances, on Tuesday and Wednesday, being deleted:

When you delete an event instance an EXDATE property is created.

The above event with EXDATE in iCalendar format:

BEGIN:VCALENDAR
…
BEGIN:VEVENT
CREATED:20151219T021727Z
DTEND;TZID=America/Toronto:20170515T110000
DTSTAMP:20151219T022251Z
DTSTART;TZID=America/Toronto:20170515T100000
EXDATE;TZID=America/Toronto:20170516T100000
EXDATE;TZID=America/Toronto:20170517T100000
LAST-MODIFIED:20151219T022251Z
RRULE:FREQ=DAILY;UNTIL=20170519T035959Z
SEQUENCE:0
SUMMARY:Meeting
TRANSP:OPAQUE
UID:21B97459-D97B-4B23-AF2A-E2759745C299
END:VEVENT
BEGIN:VEVENT
CREATED:20151219T022011Z
DTEND;TZID=America/Toronto:20170518T120000
DTSTAMP:20151219T022251Z
DTSTART;TZID=America/Toronto:20170518T110000
LAST-MODIFIED:20151219T022011Z
RECURRENCE-ID;TZID=America/Toronto:20170518T100000
SEQUENCE:0
SUMMARY:Final Meeting
TRANSP:OPAQUE
UID:21B97459-D97B-4B23-AF2A-E2759745C299
END:VEVENT
END:VCALENDAR 

UID and RECURRENCE-ID

All components within an event/to-do share the same UID. Typically this UID is also used as a calendar (.ics) file name.

Important! iOS Calendar UID is case sensitive, it requires uppercase UID only. The uppercase and lowercase UID are treated as different ids.

In addition to UID every overridden instance has its own RECURRENCE-ID which identifies the instance that this component overrides. As you can see in the above example the RECURRENCE-ID is a date and time of the specific instance in the recurrence set.

 

See also: