



                                                                C. Daboo
                                                                   Apple
                                                           June 26, 2015


             Smart Splitting of Recurring Events in CalDAV
                          caldav-recursplit-02

Abstract

   This document defines an extension to CalDAV that allows calendar
   clients to split recurring events on the server in such a way as to
   preserve the original per-attendee data, such as alarms and
   participation status.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   1
   2.  Conventions Used in This Document . . . . . . . . . . . . . .   2
   3.  New behavior  . . . . . . . . . . . . . . . . . . . . . . . .   3
     3.1.  Example . . . . . . . . . . . . . . . . . . . . . . . . .   6
   4.  Server Initiated Splitting  . . . . . . . . . . . . . . . . .   8
   5.  Security Considerations . . . . . . . . . . . . . . . . . . .   8
   6.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .   8
   7.  Normative References  . . . . . . . . . . . . . . . . . . . .   8
   Appendix A.  Acknowledgments  . . . . . . . . . . . . . . . . . .   9
   Appendix B.  Change History . . . . . . . . . . . . . . . . . . .   9
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .   9

1.  Introduction

   Internet calendaring and scheduling standards are defined by
   iCalendar [RFC5545] and iTIP [RFC5546].  The CalDAV Access [RFC4791]
   standard defines a way to access calendar data stored on a server,
   and the CalDAV Scheduling [RFC6638] draft defines how scheduling
   occurs between users of a CalDAV server.

   When dealing with recurring events defined in iCalendar, it is often
   necessary for the organizer of the events to apply a change from one
   of the recurrence instances on into the future (e.g., add a new
   attendee part way through the series of meetings). iCalendar supports
   a "RANGE" property parameter on the "RECURRENCE-ID" property that
   allows for a "THIS-AND-FUTURE" change to an existing set of recurring
   events.  However, the "RANGE" behavior is not always implemented.
   Instead, clients split the recurring series into two separate events
   (different UIDs and thus different calendar object resources stored
   in a CalDAV calendar).  One series contains all the instances up to
   the point where the change is made, and the other contains all the



Daboo                   Expires December 28, 2015               [Page 1]

                       CalDAV Recurrence Splitting             June 2015


   instances from that point onwards.  Typically this is done by
   truncating the recurrence rule in the existing resource and creating
   a new resource for the ongoing recurrence.  However, when done that
   way, it results in any per-attendee data in the original resource for
   recurrence instances after the "split point" being lost - i.e.,
   attendee loose all their status for the ongoing instances.  What is
   more, due to the requirements of CalDAV scheduling, the "PARTSTAT"
   parameter on the "ATTENDEE" properties in the new calendar object
   resource will be forcibly reset to "NEEDS-ACTION", requiring
   attendees to re-accept/decline the ongoing recurrence series in the
   new calendar object resource.  This is obviously a poor user
   experience that needs to be corrected.

   This specification defines a new CalDAV POST request action that
   causes the server to split an existing calendar object resource
   containing a recurring event, into two pieces at a specified "split
   point", such that per-attendee data and attendee participation status
   is preserved in the new calendar object resource created by the
   split.  Once that is done, clients can then modify the new resource
   to make the actual "this-and-future" change that triggers the split.

   This specification does not cover the case of splitting of scheduled
   calendar data for attendees not hosted on the CalDAV server.
   Instead, existing existing procedures for sending iTIP messages have
   to be used to update the attendee data to account for the split,
   likely resulting in loss of per-attendee data.  A future extension to
   iTIP might be possible to address that, but is not covered here.

2.  Conventions Used in This Document

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
   document are to be interpreted as described in [RFC2119].

   When XML element types in the namespaces "DAV:" and
   "urn:ietf:params:xml:ns:caldav" are referenced in this document
   outside of the context of an XML fragment, the string "DAV:" and
   "CALDAV:" will be prefixed to the element type names respectively.

   The namespace "http://calendarserver.org/ns/" is used for XML
   elements defined in this specification.  When XML element types in
   this namespace are referenced in this document outside of the context
   of an XML fragment, the string "CS:" will be prefixed to the element
   type names respectively.

   The prefix X-CALENDARSERVER- is used for all iCalendar properties,
   parameters and enumerated values defined in this extension.




Daboo                   Expires December 28, 2015               [Page 2]

                       CalDAV Recurrence Splitting             June 2015


3.  New behavior

   A server supporting the features described in this specification MUST
   include "calendarserver-recurrence-split" as a field in the DAV
   response header from an OPTIONS request on a calendar home
   collection.

   To split an existing calendar object resource containing a recurring
   event, a client issues an HTTP POST resource with the request-uri set
   to the URI of the calendar object resource.  The client also includes
   the following two URI query parameters, and one optional one:

   1.  "action" set to the value "split" - REQUIRED

   2.  "rid" set to an iCalendar format DATE or DATE-TIME value (with
       format choice determined as per description below) - REQUIRED

   3.  "uid" set to an iCalendar UID property value - OPTIONAL

   The "action" parameter is used to distinguish this operation from
   others that might be defined in the future for calendar object
   resources.

   The "rid" parameter specifies the date or date-time where the split
   is to occur.  The actual split occurs at the next recurrence instance
   on or after the "rid" parameter value - the "split point".  The "rid"
   parameter value is an iCalendar DATE or DATE-TIME value that follows
   that matched the event's DTSTART value as follows:

   +---------------------------+--------------------+------------------+
   | DTSTART value             | rid value          | rid example      |
   +---------------------------+--------------------+------------------+
   | DATE                      | DATE               | 20150626         |
   | DATE-TIME UTC             | DATE-TIME UTC      | 20150626T120000Z |
   | DATE-TIME local+time zone | DATE-TIME UTC      | 20150626T120000Z |
   | DATE-TIME floating        | DATE-TIME floating | 20150626T120000  |
   +---------------------------+--------------------+------------------+

   The optional "uid" parameter can be used by the client to specify the
   iCalendar UID property value used in the new calendar object resource
   created by the server.  In the absence of the "uid" parameter, the
   server will itself generate the UID value for the new calendar object
   resource.

   Clients MUST include both "action" and "rid" parameters in the POST
   request and MUST ensure a valid date-time value is used.  The "rid"
   parameter value MUST NOT be earlier than the start time of the first
   instance of the recurrence set, and it MUST NOT be later than the



Daboo                   Expires December 28, 2015               [Page 3]

                       CalDAV Recurrence Splitting             June 2015


   start time of the last instance of the recurrence set.  If the "rid"
   parameter value is not of the correct format or missing, the server
   MUST return a DAV:error response with the CALDAV:valid-rid-parameter
   pre-condition code.  If the "rid" parameter is valid, but outside of
   the allowed range, or the targeted calendar object resource is not
   recurring, then the server MUST return a DAV:error response with the
   CS:invalid-split pre-condition code.  The server MUST reject any
   attempt by an attendee to split their copy of a scheduled calendar
   object resource - only organizers are allowed to split events.  If
   the optional "uid" parameter is used by the client, and the server
   determines that the specified value is invalid (e.g., too short or
   too long as per reasonable requirements), then it MUST return a
   DAV:error response with the CS:invalid-split pre-condition code.

   Clients MAY include an HTTP "Prefer" request header including the
   value "return=representation" (see [RFC7240]).  That instructs the
   server to return a WebDAV multistatus response containing two
   responses: one for the targeted resource and one for the new resource
   created as a result of the split.  The multistatus response MUST
   include the DAV:getetag and CALDAV:calendar-data properties for each
   resource.  In the absence of the "Prefer:return=representation"
   request header, the server MUST return an HTTP "Split-Component-URL"
   response header whose value is the URI of the new resource created as
   a result of the split.

   When a server receives a valid split request as described above, it
   does the equivalent of the following:

   1.  The existing resource is duplicated, preserving any per-user data
       such as alarms or transparency status.

   2.  The calendar data in the existing resource is modified as
       follows:

       A.  Any overridden components with a "RECURRENCE-ID" property
           value prior to the split point are removed.

       B.  Any "RDATE" or "EXDATE" property values prior to the split
           point are removed.

       C.  Any "RRULE" property that only generates instances prior to
           the split point is removed.

       D.  Any remaining "RRULE" property has its "COUNT" value adjusted
           by subtracting the number of instances prior to the split
           point.





Daboo                   Expires December 28, 2015               [Page 4]

                       CalDAV Recurrence Splitting             June 2015


       E.  The "DTSTART" property of the master instance is adjusted to
           the value of the first instance of the "RRULE" on or after
           the split point, or, in the absence of an "RRULE", to the
           first "RDATE" property value on or after the split point.

   3.  The calendar data in the new resource is modified as follows:

       A.  Any overridden components with a "RECURRENCE-ID" property
           value on or after the split point are removed.

       B.  Any "RDATE" or "EXDATE" property values on or after the split
           point are removed.

       C.  Any "RRULE" property that only generates instances on or
           after the split point is removed.

       D.  Any remaining "RRULE" property has an "UNTIL" value applied,
           with the until value being one second (for a "rid" DATE-TIME
           value) or one day (for a "rid" DATE value) less than the
           split point.

       E.  The "UID" property of all components is changed to (the same)
           new value.

       F.  Attendee participation status MUST NOT be changed.

   4.  The server MUST add a "RELATED-TO" property, with a "RELTYPE"
       parameter set to "X-CALENDARSERVER-RECURRENCE-SET", to all
       components of the existing and new resources, if one does not
       already exist.  The new property value is set to a new auto-
       generated "UID" value.

   When an organizer splits a scheduled event, the server performs the
   following actions:

   1.  For each attendee hosted on the same server, the server MUST
       split the attendee's copy of the event in accordance with the
       split point used by the organizer.  In doing so, it MUST preserve
       any per-attendee state (alarms, transparency, participation
       status) in the new resource (which also MUST have the same "UID"
       property value as the organizer's new resource).

   2.  For each attendee not hosted on the same server, the server will
       need to send a series of iTIP messages to correctly update the
       attendee with both the modified (old) resource data and the new
       resource.  This will likely result in loss of per-attendee data
       such as alarms (though the participation status might be




Daboo                   Expires December 28, 2015               [Page 5]

                       CalDAV Recurrence Splitting             June 2015


       preserved if the calendar user agent processing the new iTIP
       message for the new resource allows it).

   Note that, since attendees can be invited to specific instances of a
   recurring meeting (not necessarily the entire set), it is possible
   that either the old or new calendar data no longer contains any valid
   components since the attendee was not invited to the corresponding
   portions of the original split recurrence.  In such cases, the server
   MUST remove the original resource, or MUST NOT create the new
   resource.

3.1.  Example

   Assume the following iCalendar data is stored in the resource with
   URI "/event.ics":

   BEGIN:VCALENDAR
   PRODID:-//Example Inc.//Example Calendar//EN
   VERSION:2.0
   BEGIN:VEVENT
   DTSTAMP:20140110T135358Z
   DTSTART:20140101T120000Z
   DURATION:PT1H
   SUMMARY:Example
   UID:DF400028-1223-4D26-92CA-B0ED3CC161F3
   RRULE:FREQ=DAILY;COUNT=20
   END:VEVENT
   END:VCALENDAR

   The client issues a POST split request to split the recurring event
   at the instance with date-time "20140110T120000Z":

   >> Request <<

   POST /event.ics?action=split&rid=20140110T120000Z HTTP/1.1
   Host: cal.example.com
   Content-Length: 0
   Prefer: return=representation


   >> Response <<

   HTTP/1.1 207 Multi-Status
   ETag: "5bc9a2b55081eba0a9cd34f742aa1c11"
   Date: Fri, 10 Jan 2014 14:02:20 GMT
   Content-Type: text/xml
   Content-Length: xxxx




Daboo                   Expires December 28, 2015               [Page 6]

                       CalDAV Recurrence Splitting             June 2015


   <?xml version='1.0' encoding='UTF-8'?>
   <multistatus xmlns='DAV:'>
     <response>
       <href>/event.ics</href>
       <propstat>
         <prop>
           <getetag>"5bc9a2b55081eba0a9cd34f742aa1c11"</getetag>
           <calendar-data xmlns='urn:ietf:params:xml:ns:caldav'
   >BEGIN:VCALENDAR
   VERSION:2.0
   PRODID:-//Example Inc.//Example Calendar//EN
   BEGIN:VEVENT
   UID:DF400028-1223-4D26-92CA-B0ED3CC161F3
   DTSTART:20140110T120000Z
   DURATION:PT1H
   DTSTAMP:20140110T135358Z
   RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:8DE45ECB-8145-
    4AEC-B3E1-11A9DB22A578
   RRULE:FREQ=DAILY;COUNT=11
   SUMMARY:Example
   END:VEVENT
   END:VCALENDAR
   </calendar-data>
         </prop>
         <status>HTTP/1.1 200 OK</status>
       </propstat>
     </response>
     <response>
       <href>/event-split.ics</href>
       <propstat>
         <prop>
           <getetag>"8b352ad2e0ca26c99cb205373b3dc34c"</getetag>
           <calendar-data xmlns='urn:ietf:params:xml:ns:caldav'
   >BEGIN:VCALENDAR
   VERSION:2.0
   PRODID:-//Example Inc.//Example Calendar//EN
   BEGIN:VEVENT
   UID:E3B9D6D4-E19F-47AA-9088-1A29A9A7030F
   DTSTART:20140110T120000Z
   DURATION:PT1H
   DTSTAMP:20140110T135358Z
   RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:8DE45ECB-8145-
    4AEC-B3E1-11A9DB22A578
   RRULE:FREQ=DAILY;UNTIL=20140110T115959Z
   SUMMARY:Example
   END:VEVENT
   END:VCALENDAR
   </calendar-data>



Daboo                   Expires December 28, 2015               [Page 7]

                       CalDAV Recurrence Splitting             June 2015


         </prop>
         <status>HTTP/1.1 200 OK</status>
       </propstat>
     </response>
   </multistatus>

   The original resource is changed to have a start date-time value of
   "20140110T120000Z", and the "COUNT" component of the "RRULE" property
   is adjusted to the value "11" (which represents the number of
   remaining instances for that event, 9 early instances having been
   removed).  The new resource has the original start date-time value,
   and its "RRULE" property has an "UNTIL" value one second prior to the
   split point.  Both resources have a "RELATED-TO" property with a
   "RELTYPE" parameter set to "X-CALENDARSERVER-RECURRENCE-SET" and a
   value set to a new "UID" value.

4.  Server Initiated Splitting

   Servers can automatically split events that have already been stored
   by the client.  The trigger for such splitting is up to the server
   (e.g., it can split when a recurring event exceeds a certain size, or
   when a certain number of instances are now in the past).  When
   splitting, the server MUST use the approach outlined above - namely
   create a new calendar object resource for the past instances,
   truncate the existing calendar data and use the "RELATED_TO" property
   to link them.  In other words, this will look exactly like a client-
   initiated split.

5.  Security Considerations

   This specification does not introduce any more security
   considerations beyond those already listed in iCalendar [RFC5545],
   iTIP [RFC5546] and CalDAV Access [RFC4791] and CalDAV Scheduling
   [RFC6638].

6.  IANA Considerations

   TBD: new HTTP request header registration.

7.  Normative References

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997.

   [RFC4791]  Daboo, C., Desruisseaux, B., and L. Dusseault,
              "Calendaring Extensions to WebDAV (CalDAV)", RFC 4791,
              March 2007.




Daboo                   Expires December 28, 2015               [Page 8]

                       CalDAV Recurrence Splitting             June 2015


   [RFC5545]  Desruisseaux, B., "Internet Calendaring and Scheduling
              Core Object Specification (iCalendar)", RFC 5545,
              September 2009.

   [RFC5546]  Daboo, C., "iCalendar Transport-Independent
              Interoperability Protocol (iTIP)", RFC 5546, December
              2009.

   [RFC6638]  Daboo, C. and B. Desruisseaux, "Scheduling Extensions to
              CalDAV", RFC 6638, June 2012.

   [RFC7240]  Snell, J., "Prefer Header for HTTP", RFC 7240, June 2014.

Appendix A.  Acknowledgments

   This specification is the result of discussions between the Apple
   calendar server and client teams.

Appendix B.  Change History

   Changes since -02

   1.  Clarify that rid query parameter value matches the event DTSTART
       value type using the UNTIL "rules"

   2.  Clarify that earlier event uses an UNTIL one second or one day
       less that the "rid" value depending on the value type.

   Changes since -01

   1.  Added "uid" query parameter to POST request

   2.  New "RELATED-TO" is now a new UID value not the value of the new
       resource

Author's Address

   Cyrus Daboo
   Apple Inc.
   1 Infinite Loop
   Cupertino, CA  95014
   USA

   Email: cyrus@daboo.name
   URI:   http://www.apple.com/






Daboo                   Expires December 28, 2015               [Page 9]
