RFC 7529
Non-Gregorian Recurrence Rules in the Internet Calendaring and Scheduling Core Object Specification (iCalendar)
Non-Gregorian Recurrence Rules in the Internet Calendaring and Scheduling Core Object Specification (iCalendar) ๐
- RFC number: RFC 7529 ๐
- Authors: C. Daboo (Apple Inc.) and G. Yakushev (Google Inc.) ๐๐
- Category: Standards Track โจ
- ISSN: 2070-1721
- Date: May 2015 ๐๏ธ
- Updates: RFC 5545, RFC 6321, and RFC 7265 ๐
okay so this doc is about getting non-Gregorian recurrence rules into iCalendar, the format we all use for calendar data ๐ it's giving "we need more calendars in our lives." ๐
Abstract โจ
okay so this document extends iCalendar (RFC 5545) so it can handle non-Gregorian recurrence rules ๐ธ it also explains how CalDAV (RFC 4791) servers and clients can be extended to support these new rules, which is so iconic ๐
Status of This Memo ๐
this is an Internet Standards Track document ๐ฆ
it's a product of the Internet Engineering Task Force (IETF), so it represents the consensus of the IETF community ๐ซถ it got public review and was approved for publication by the Internet Engineering Steering Group (IESG). more info on Internet Standards is in Section 2 of RFC 5741 ๐
info about the current status of this doc, any errata, and how to give feedback is at http://www.rfc-editor.org/info/rfc7529 ๐
Copyright Notice โ๏ธ
Copyright (c) 2015 IETF Trust and the persons identified as the document authors. All rights reserved. ๐
this document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as in effect on the date of publication. please read these carefully, because they describe your rights and restrictions for this doc ๐ง code components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they're provided without warranty as described in the Simplified BSD License. ๐ซง
Table of Contents ๐๏ธ
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Conventions Used in This Document . . . . . . . . . . . . . . 3
3. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . 4
4. Extended RRULE Property . . . . . . . . . . . . . . . . . . . 6
4.1. Skipping Invalid Dates . . . . . . . . . . . . . . . . . 6
4.2. Handling Leap Months . . . . . . . . . . . . . . . . . . 9
4.3. Examples . . . . . . . . . . . . . . . . . . . . . . . . 10
5. Registering Calendar Systems . . . . . . . . . . . . . . . . 13
6. Compatibility . . . . . . . . . . . . . . . . . . . . . . . . 13
7. Use with iTIP . . . . . . . . . . . . . . . . . . . . . . . . 14
8. Use with xCal . . . . . . . . . . . . . . . . . . . . . . . . 15
9. Use with jCal . . . . . . . . . . . . . . . . . . . . . . . . 15
10. Use with CalDAV . . . . . . . . . . . . . . . . . . . . . . . 16
10.1. CALDAV:supported-rscale-set Property . . . . . . . . . . 17
11. Security Considerations . . . . . . . . . . . . . . . . . . . 18
12. References . . . . . . . . . . . . . . . . . . . . . . . . . 18
12.1. Normative References . . . . . . . . . . . . . . . . . . 18
12.2. Informative References . . . . . . . . . . . . . . . . . 19
Appendix A. xCal RELAX NG Schema Update . . . . . . . . . . . . 20
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 21
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 21
1. Introduction ๐ท
okay so iCalendar [RFC5545] is everywhere, and it represents dates and times using only the Gregorian calendar system ๐ it does have a way to use other calendar systems through a CALSCALE property, but that has never actually been used ๐ still, we need at least non-Gregorian recurrence patterns for anniversaries and lots of local, religious, or civil holidays that are based on non-Gregorian dates ๐
using the existing CALSCALE property for non-Gregorian calendars has a couple of problems, bestie:
- The
CALSCALEproperty lives in the top-levelVCALENDARobject, so it applies to every component inside that object. in today's multi-cultural world, that's a big restriction, because you can't mix events from different calendar systems in the same iCalendar object. for example, you couldn't have both the Gregorian New Year and the Chinese New Year in one object ๐งง - Time zone and daylight saving time rules are usually published using Gregorian dates and rules (like "the 3rd Sunday in March"), so they get converted into
VTIMEZONEcomponents that use Gregorian dates and recurrence rules. that means theVTIMEZONEis stuck on the Gregorian calendar, but aVEVENTmight want a different non-Gregorian calendar scale. so the single top-levelCALSCALEproperty is still not enough ๐ญ
this spec fixes that by keeping CALSCALE set to Gregorian and redefining the RRULE recurrence rule property so it accepts new items, including one that lets non-Gregorian calendar systems be used ๐
so all the DATE, DATE-TIME, and PERIOD values in the iCalendar object stay in the Gregorian calendar system, but repeating patterns can be defined in other calendar systems too โจ it's then up to calendar user agents and servers to map between Gregorian and non-Gregorian calendar systems when they expand recurrence instances ๐ง the non-Gregorian recurrence rules can be used in any iCalendar component that allows the RRULE property, including VTIMEZONE components (to allow for possible future use of non-Gregorian rules in published daylight saving time data) ๐
this spec doesn't define calendar systems itself ๐ โโ๏ธ instead, it uses the calendar system registry defined by the Unicode Consortium in their Common Locale Data Repository (CLDR) project [UNICODE.CLDR], as implemented in the Unicode (International Components for Unicode (ICU)) Library [UNICODE.ICU] ๐ซถ
this spec makes the following updates, and it's giving organized:
It updates iCalendar [RFC5545], the XML format for iCalendar (xCal) [RFC6321], and the JSON format for iCalendar (jCal) [RFC7265], to extend theRRULEproperty definition. It clarifies use of the iCalendar Transport-Independent Interoperability Protocol (iTIP) [RFC5546] to specify how the extendedRRULEproperty should be handled in iTIP messages. It extends CalDAV [RFC4791] to specify how the extendedRRULEproperty can be supported by CalDAV servers and clients.
2. Conventions Used in This Document ๐
the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this doc are to be interpreted as described in [RFC2119] ๐ง
the notation in this memo is the ABNF notation of [RFC5234], as used by iCalendar [RFC5545] โ๏ธ any syntax elements shown below that aren't explicitly defined in this spec come from iCalendar [RFC5545], iTIP [RFC5546], and CalDAV [RFC4791] ๐
when XML element types in the namespaces "DAV:" and "urn:ietf:params:xml:ns:caldav" are referenced outside of an XML fragment, the strings "DAV:" and "CALDAV:" get prefixed to the element type names, respectively ๐ท๏ธ
when a Gregorian calendar date is shown in text, it uses the format YYYYMMDD, where YYYY is the 4-digit year, MM is the 2-digit month, and DD is the 2-digit day (same format as iCalendar [RFC5545]) ๐
the Chinese calendar is used as the example of a non-Gregorian calendar for illustration ๐งง when a Chinese calendar date is shown in text, it uses the format {C}YYYYMM[L]DD. so it's the same as Gregorian but with a {C} prefix, plus an optional L after the month to mark a leap month ๐ similarly, {E} and {H} are used in other examples as prefixes for Ethiopic (Amete Mihret) and Hebrew dates ๐ช๐น๐
the {} prefix is purely for illustration and never shows up in actual dates used in iCalendar or related specs ๐ซง also, the Chinese calendar years in the examples are based on the Unicode (ICU) [UNICODE.ICU] library's Chinese calendar epoch. there are several different Chinese calendar epochs in common use, but picking one over another doesn't change the actual calculation of the Gregorian equivalent dates, as long as the conversion is always done with the same epoch ๐ซถ
to be continued... ๐โจ
3. Overview ๐ธ
okay so the Gregorian calendar, the one we all use, has 12 months ๐ Each month has a fixed number of days, either 30 or 31, except February, which has 28 or 29 (29 in a leap year). Weeks are 7 days long, with the names Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, and Sunday. A year can be 365 or 366 days (366 in a leap year). The number of whole weeks in a year is 52, but the [ISO.8601.2004] week numbering scheme that iCalendar [RFC5545] uses can count up to 53 โจ
In iCalendar, the "RECUR" value type has a bunch of fields for describing a recurrence pattern, and those fields get their limits from the Gregorian calendar. other calendar systems can have different limits and different behaviours that need to be handled, so this specification doesn't cover the maximum values for the elements in the "RECUR" value ๐ฆ
So how do we generate recurring instances in a non-Gregorian calendar? We use these principles:
- iCalendar data keeps using the "GREGORIAN" calendar system, so all "DATE", "DATE-TIME", and "PERIOD" values keep using the Gregorian format and limits ๐
- The "RRULE" property gets extended with an "RSCALE" element in its value, which says which calendar system to use for the recurrence pattern. The existing elements of the "RRULE" value type are still used, but they're modified to support different upper limits based on the "RSCALE" value. Month numbers are also modified so a leap month can be specified ๐ All the existing requirements for "RRULE" still apply (for example, the "RRULE" has to match the "DTSTART" value of the master instance). Other recurrence properties, like "RECURRENCE-ID", "RDATE", and "EXDATE", keep using the Gregorian date format, because "CALSCALE" is unchanged ๐
When generating instances, the following procedure might be used:
- Convert the "DTSTART" property value of the master recurring component into the date and time components for the calendar system specified by the "RSCALE" element in the "RRULE" value. This gives you the "seed" value for generating the later recurrence instances ๐ฑ
- Iteratively generate instances by applying the "RRULE" value to the year, month, and day components of the date in the new calendar system ๐
- For each generated instance, convert the dates and times back from the non-Gregorian form into Gregorian, and use those values for other properties like "RECURRENCE-ID" ๐ซถ
Let's look at an example for an event that's the Chinese New Year ๐งง
DTSTART;VALUE=DATE:20130210
RRULE:RSCALE=CHINESE;FREQ=YEARLY
SUMMARY:Chinese New Year
To generate the instances, first the "DTSTART" value "20130210" gets converted into the Chinese calendar system, giving "{C}46500101". Next, the year component is incremented by one to give "{C}46510101", and that gets converted back into Gregorian as "20140131". More instances are generated by repeatedly increasing the year component in the Chinese date and converting back to Gregorian ๐
4. Extended RRULE Property โจ
okay bestie, this section is where the actual magic happens ๐ฎ This specification extends the existing "RRULE" iCalendar property value with a new "RSCALE" element, which says which calendar system is used to generate the recurrence pattern ๐
When "RSCALE" is present, the other changes to "RRULE" are:
- Elements that include numeric values (for example, "BYYEARDAY") have numeric ranges defined by the "RSCALE" value. This is because some calendar systems have more than 366 days in a year ๐
- Month numbers can include an "L" suffix to show that the specified month is a leap month in the corresponding calendar system (see Section 4.2) ๐
- A "SKIP" element is added to define how "missing" instances are handled (see Section 4.1) ๐ฆ
The syntax for the "RECUR" value gets modified like this:
; recur-rule-part is extended from RFC 5545
recur-rule-part =/ ("RSCALE" "=" rscale)
/ ("SKIP" "=" skip)
rscale = (iana-token ; A CLDR-registered calendar system
; name.
/ x-name) ; A non-standard, experimental
; calendar system name.
; Names are case insensitive,
; but uppercase values are preferred.
skip = ("OMIT" / "BACKWARD" / "FORWARD")
; Optional, with default value "OMIT", and
; MUST NOT be present unless "RSCALE" is present.
monthnum = 1*2DIGIT ["L"]
; Existing element modified to include a leap
; month indicator suffix.
4.1. Skipping Invalid Dates ๐
In every calendar system, only certain combinations of day-of-month and month are valid for a given year. For example, in the Gregorian calendar, January 31st is valid but February 31st is not. Similarly, February 29th is valid in a leap year but invalid in a non-leap year. Other calendar systems can also include leap months (see Section 4.2), which vary from year to year. This is a problem for recurring events, because the frequency of recurrence might give rise to an invalid date. For example, a recurring event that starts on January 31st and repeats monthly will generate invalid dates for months with fewer than 31 days ๐
The iCalendar [RFC5545] specification requires recurrence rule generators to ignore any invalid dates generated when iterating the rule. However, that behaviour might be surprising to a calendar user born on a leap day, whose birthday event only shows up on their calendar every four years ๐ Humans have common conventions for what to do in these cases, but those conventions can differ from calendar system to calendar system, and even within the same calendar system, depending on the nature of the event. Typically, humans expect the "missing" events to be moved to an earlier or later (valid) date ๐ฅน
This specification introduces a new "RRULE" element, "SKIP", for use only when the "RSCALE" element is present. The "SKIP" element lets the calendar user agent specify new options for handling invalid dates ๐ง
- "SKIP=OMIT": this is the default option, and it corresponds to the existing iCalendar behaviour of simply ignoring the invalid date.
- "SKIP=BACKWARD": when this option is set, a date with an invalid month is changed to the previous (valid) month. A date with an invalid day-of-month is changed to the previous (valid) day-of-month.
- "SKIP=FORWARD": when this option is set, a date with an invalid month is changed to the next (valid) month. A date with an invalid day-of-month is changed to the next (valid) day-of-month.
Note that for both "BACKWARD" and "FORWARD", if the month is changed and that results in an invalid day-of-month, then the skip behaviour gets reapplied as per the day-of-month rules, according to the processing order defined below ๐
The month and day-of-month skip behaviour is only applied at specific points during the processing of an "RRULE". Those points are decided by the order in which any "BYxxx" elements are processed. The order is as follows (based on the "RRULE" element processing order defined in Section 3.3.10 of [RFC5545]) ๐
BYMONTHSKIP(for invalid month only)BYWEEKNOBYYEARDAYBYMONTHDAYSKIP(for invalid day)BYDAYBYHOURBYMINUTEBYSECONDBYSETPOSCOUNTUNTIL
It's often possible to avoid dealing with invalid dates altogether by figuring out what a human user really means ๐ง For example, a human creating a monthly recurring event that starts on January 31st probably wants the event on the last day of every month. In that case, you could encode it into an "RRULE" using the "BYMONTHDAY=-1" element ๐
Only a few types of recurrence patterns are likely to need "SKIP". Here's a list of some situations where it might be needed:
- The start date of the recurrence is a leap day in the specified calendar system.
- The start date of the recurrence is in a leap month in the specified calendar system.
- The start date of the recurrence has a day-of-month value greater than the smallest day-of-month value for any month in any year in the specified calendar system.
- A "BYMONTHDAY" element in an "RRULE" has a day-of-month value greater than the smallest day-of-month value for any month in any year in the specified calendar system.
- A "BYMONTH" element in an "RRULE" has a value corresponding to a leap month in the specified calendar system.
- A combination of a "BYMONTHDAY" element and a "BYMONTH" element in an "RRULE" has a value corresponding to a leap day in the specified calendar system.
- A "BYYEARDAY" element in an "RRULE" has an absolute value greater than the smallest number of days in any year in the specified calendar system.
- A "BYWEEKNO" element in an "RRULE" has an absolute value greater than the smallest number of weeks in any year in the specified calendar system.
Examples of using "SKIP" for some common use cases appear in Section 4.3 ๐
4.2. Handling Leap Months ๐
Leap months can occur in different calendar systems. For those calendar systems, the following rules apply when "identifying" months:
- Numeric values 1 through N are used to identify regular, non-leap, months (where N is the number of months in a regular, non-leap, year).
- The suffix "L" is added to the regular month number to indicate a leap month that follows the regular month. For example, "5L" is a leap month that follows the 5th regular month in the year.
Be careful when mapping the month identifiers used here to those of any underlying calendar system library you're using ๐จ In particular, the Hebrew calendar system used by Unicode (ICU) [UNICODE.ICU] uses a month number scheme of 1 through 13, with month 6 being the leap month. In non-leap years, month 6 is skipped. So ICU months 1 through 5 map to iCalendar months 1 through 5, ICU month 6 maps to iCalendar month "5L", and ICU months 7 through 13 map to iCalendar months 6 through 12 ๐
4.3. Examples โจ
4.3.1. Chinese New Year ๐งง
Okay, so check out this set of iCalendar properties (from the example above) ๐
DTSTART;VALUE=DATE:20130210
RRULE:RSCALE=CHINESE;FREQ=YEARLY
SUMMARY:Chinese New Year
These make a recurring event for the Chinese New Year, and the first instance is the one in Gregorian year 2013 ๐
The Chinese date for that first instance is {C}46500101. The table below shows the first instance plus the next four. Each one comes from adding the right amount to the year part of the Chinese date. There's also the conversion back to the Gregorian date โจ
+--------------+--------------------------+
| Chinese Date | Gregorian Date |
+--------------+--------------------------+
| {C}46500101 | 20130210 - DTSTART value |
| {C}46510101 | 20140131 |
| {C}46520101 | 20150219 |
| {C}46530101 | 20160208 |
| {C}46540101 | 20170128 |
+--------------+--------------------------+
4.3.2. Ethiopic 13th Month ๐ธ
Here's the next one, bestie ๐ฆ
DTSTART;VALUE=DATE:20130906
RRULE:RSCALE=ETHIOPIC;FREQ=MONTHLY;BYMONTH=13
SUMMARY:First day of 13th month
These make a recurring event for the first day of the 13th month, and the first instance is the one in Gregorian year 2013. There are a bunch of other ways to write that RRULE and get the same dates, but this one was picked on purpose to show off a BYMONTH value going past 12, which is something iCalendar originally didn't allow (Section 3.3.10 of [RFC5545]). Iconic behavior ๐
The Ethiopic date for the first instance is {E}20051301. The table below shows that instance plus the next four, each made by adding the right amount to the year part of the Ethiopic date. Also included is the conversion back to Gregorian ๐
+---------------+--------------------------+
| Ethiopic Date | Gregorian Date |
+---------------+--------------------------+
| {E}20051301 | 20130906 - DTSTART value |
| {E}20061301 | 20140906 |
| {E}20071301 | 20150906 |
| {E}20081301 | 20160906 |
| {E}20091301 | 20170906 |
+---------------+--------------------------+
Note that in this example, the BYMONTH part of the RRULE matches the Ethiopic month number and not the Gregorian month ๐
4.3.3. Hebrew Anniversary Starting in a Leap Month ๐
Consider this set of iCalendar properties ๐ง
DTSTART;VALUE=DATE:20140208
RRULE:RSCALE=HEBREW;FREQ=YEARLY;BYMONTH=5L;BYMONTHDAY=8;SKIP=FORWARD
SUMMARY:Anniversary
These make a recurring event for the 8th day of the Hebrew month Adar I (the leap month marked by 5L), and the first instance is the one in Gregorian year 2014 ๐
The Hebrew date for the first instance is {H}577405L08, which is a leap month in year 5774. The table below shows that instance plus the next four. Each one comes from adding the right amount to the year part of the Hebrew date, and the fact that only year 5776 is a leap year matters here. So in the other years, the Hebrew month part gets pushed forward to month 6. The conversion back to Gregorian is included too ๐ฅ
+--------------+--------------------------+
| Hebrew Date | Gregorian Date |
+--------------+--------------------------+
| {H}577405L08 | 20140208 - DTSTART value |
| {H}57750608 | 20150227 |
| {H}577605L08 | 20160217 |
| {H}57770608 | 20170306 |
| {H}57780608 | 20180223 |
+--------------+--------------------------+
4.3.4. Gregorian Leap Day with SKIP ๐
Consider this set of iCalendar properties (this one's so relatable ๐ญ)
DTSTART;VALUE=DATE:20120229
RRULE:FREQ=YEARLY
SUMMARY:Anniversary
These make a recurring event for February 29th, 2012, in the standard iCalendar calendar scale, which is Gregorian. The normal iCalendar behavior is that dates that don't exist in a recurrence set just get ignored. So these properties would only produce instances in leap years (2016, 2020, and so on), which is probably not what users are hoping for ๐ฅบ The new RSCALE option from this spec comes with a SKIP element that can "fill in" those missing instances in a sensible way. The set below does exactly that ๐
DTSTART;VALUE=DATE:20120229
RRULE:RSCALE=GREGORIAN;FREQ=YEARLY;SKIP=FORWARD
SUMMARY:Anniversary
With these properties, the "missing" instances in non-leap years land on March 1st of those years ๐
+-------------------------------+----------------------------+
| Instances (with SKIP=FORWARD) | Instances (without RSCALE) |
+-------------------------------+----------------------------+
| 20120229 | 20120229 - DTSTART value |
| 20130301 | |
| 20140301 | |
| 20150301 | |
| 20160229 | 20160229 |
| 20170301 | |
+-------------------------------+----------------------------+
5. Registering Calendar Systems ๐๏ธ
This spec uses the Unicode Consortium's registry of calendar systems [UNICODE.CLDR] to decide which values are valid for the RSCALE element of an RRULE. Heads up: the underscore character _ never shows up in CLDR-based calendar system names. New values can be added to this registry by following Unicode Consortium rules. A lot of non-Gregorian calendar implementations are going to use the software libraries from Unicode (ICU) [UNICODE.ICU], so it makes total sense to reuse their registry instead of making a brand new one ๐ง RSCALE values are case insensitive, but uppercase is the preferred look ๐
CLDR also supports "alias" values, which are alternative names for certain calendar systems. These aliases can be used as RSCALE values, and they get treated exactly like the CLDR calendar system they alias โจ
When you're using CLDR data, calendar agents SHOULD take the "deprecated" value into account and switch over to the "preferred" calendar system instead. For example, the islamicc calendar system counts as deprecated in favor of islamic-civil ๐
6. Compatibility ๐ซถ
For calendar user agents that don't support the RSCALE element, or that don't support the calendar system named by the RSCALE element value, these are the possible behaviors when processing iCalendar data:
- The calendar user agent can reject the entire iCalendar object that contains at least one iCalendar component using the unrecognized
RSCALEelement or element value. - The calendar user agent can reject just the iCalendar components that contain an unrecognized
RSCALEelement or element value. Note that any overridden components tied to those rejected components MUST also be rejected (meaning any other components sharing the sameUIDproperty value as the one with the unrecognizedRSCALEelement or element value). - The calendar user agent can fall back to non-recurring behavior for the iCalendar component that contains the unrecognized
RSCALEelement or element value (basically ignoring theRRULEproperty). However, any overridden components SHOULD be rejected, since they'd be "orphaned" instances that look totally out of place ๐
In general, option (2) above is the best choice for a calendar user agent, since it's the least disruptive one ๐ฆ Note that when processing iTIP [RFC5546] messages, the way the rejection happens is covered in the next section ๐
7. Use with iTIP ๐จ
iTIP [RFC5546] defines how iCalendar data can be sent between calendar user agents so calendar components can be scheduled between calendar users. A lot of the time you can't know what a calendar user agent receiving an iTIP message can do, but iTIP has fallback behavior for those situations ๐ธ
For calendar user agents that don't support the RSCALE element, here's what can happen when iTIP messages with an RSCALE element arrive:
- The receiving calendar user agent can reject the entire iTIP message and send back an iTIP reply with a
REQUEST-STATUSproperty set to the3.1status code (as per Section 3.6.14 of [RFC5546]). - The receiving calendar user agent can fall back to non-recurring behavior for the calendar component (basically ignoring the
RRULEproperty), and send back an iTIP reply with aREQUEST-STATUSproperty set to the2.3,2.5,2.8, or2.10status codes (as per Sections 3.6.4, 3.6.6, 3.6.9, or 3.6.11, respectively, of [RFC5546]).
For calendar user agents that do support the RSCALE element but don't support the calendar system named by the RSCALE element value, here's what can happen:
- The iTIP message SHOULD be rejected, with a
REQUEST-STATUSproperty set to the3.1status code (as per Section 3.6.14 of [RFC5546]). - If the iTIP message is accepted and the calendar component is treated as non-recurring, an iTIP reply with a
REQUEST-STATUSproperty set to the2.8or2.10status codes (as per Sections 3.6.9 or 3.6.11, respectively, of [RFC5546]) SHOULD be sent back ๐
As noted in Section 6, the best choice is to reject the entire iTIP message ๐
8. Use with xCal ๐ง
xCal [RFC6321] defines how iCalendar data is represented in XML. This spec extends the <recur> XML element from Section 3.6.10 of [RFC6321] like so:
- A new
<rscale>XML element is defined as a child element of<recur>. The content of this element MUST be a string whose value is theRSCALEelement value of theRRULE, with case preserved. - A new
<skip>XML element is defined as a child element of<recur>. The content of this element MUST be a string whose value is theSKIPelement value of theRRULE, with case preserved. - The
<bymonth>XML element is redefined to support either numeric or string values as its content (as per Section 4.2).
Extensions to the RELAX NG schema in Appendix A of [RFC6321] are defined in Appendix A of this document ๐ง
Example: the iCalendar RRULE property:
RRULE:RSCALE=GREGORIAN;FREQ=YEARLY;SKIP=FORWARD
would be represented in XML as:
<rrule>
<recur>
<rscale>GREGORIAN</rscale>
<freq>YEARLY</freq>
<skip>FORWARD</skip>
</recur>
</rrule>
9. Use with jCal โจ
okay so jCal [RFC7265] is the JSON way of writing iCalendar data ๐ and this spec glams up the "recur" JSON object from Section 3.6.10 of [RFC7265] in three ways:
- A new "rscale" child member is defined. It MUST be a string whose value is the "RSCALE" element value of the "RRULE", with case preserved.
- A new "skip" child member is defined. It MUST be a string whose value is the "SKIP" element value of the "RRULE", with case preserved.
- The "bymonth" child member is redefined to support either numeric or string values. If the "BYMONTH" element value is an integer, then a numeric JSON value MUST be used. If the "BYMONTH" element value is an integer with the "L" suffix (as per Section 4.2), then a JSON string value MUST be used.
Example: the iCalendar "RRULE" property:
RRULE:RSCALE=GREGORIAN;FREQ=YEARLY;SKIP=FORWARD
would be represented in JSON as:
[
"rrule",
{},
"recur",
{
"rscale": "GREGORIAN",
"freq": "YEARLY",
"skip": "FORWARD"
}
]
10. Use with CalDAV ๐ฆ
the CalDAV [RFC4791] calendar access protocol lets clients and servers swap iCalendar data ๐ and CalDAV clients can also query the calendar data stored on the server, including time-based queries. since an "RSCALE" element value decides the time ranges for recurring instances in a calendar component, CalDAV servers need to support it so they can interoperate with clients that are also using the "RSCALE" element. no cap, this part matters a lot ๐ญ
a CalDAV server advertises a CALDAV:supported-rscale-set Web Distributed Authoring and Versioning (WebDAV) property on calendar home or calendar collections if it supports use of the "RSCALE" element as described in this specification. the server can advertise a specific set of supported calendar systems by including one or more CALDAV:supported-rscale XML elements within the CALDAV:supported-rscale-set XML element. if no CALDAV:supported-rscale XML elements are included in the WebDAV property, then clients can try any calendar system value but need to be prepared for a failure when attempting to store the calendar data. ๐
Clients MUST NOT attempt to store iCalendar data containing "RSCALE" elements if the CALDAV:supported-rscale-set WebDAV property is not advertised by the server. ๐ซ
the server SHOULD return an HTTP 403 response with a DAV:error element containing a CALDAV:supported-rscale XML element, if a client attempts to store iCalendar data with an "RSCALE" element value not supported by the server. โจ
it's possible for an "RSCALE" value to be present in calendar data on the server being accessed by a client that doesn't support an "RSCALE" element or its specified value. it's expected that existing clients, unaware of "RSCALE", will fail gracefully by ignoring the calendar component, while still processing other calendar data on the server (as per option (2) in Section 6). iconic behavior honestly ๐ธ
10.1. CALDAV:supported-rscale-set Property ๐ง
Name: supported-rscale-set
Namespace: urn:ietf:params:xml:ns:caldav
Purpose: Enumerates the set of supported iCalendar "RSCALE" element values supported by the server.
Protected: This property MUST be protected and SHOULD NOT be returned by a PROPFIND allprop request (as defined in Section 14.2 of [RFC4918]).
Description: See above.
Definition:
<!ELEMENT supported-rscale-set (supported-rscale*)>
<!ELEMENT supported-rscale (#PCDATA)>
<!-- PCDATA value: string - case insensitive but
uppercase preferred -->
Example:
<C:supported-rscale-set
xmlns:C="urn:ietf:params:xml:ns:caldav">
<C:supported-rscale>GREGORIAN</C:supported-rscale>
<C:supported-rscale>CHINESE</C:supported-rscale>
<C:supported-rscale>ISLAMIC-CIVIL</C:supported-rscale>
<C:supported-rscale>HEBREW</C:supported-rscale>
<C:supported-rscale>ETHIOPIC</C:supported-rscale>
</C:supported-rscale-set>
11. Security Considerations ๐ฅ
๐จ bestie, security is the main character here, so please read this one properly ๐จ
This specification does not introduce any additional security concerns beyond those described in [RFC5545], [RFC5546], and [RFC4791]. ๐ซถ
12. References ๐
12.1. Normative References
[RFC2119]Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997,<http://www.rfc-editor.org/info/rfc2119>.[RFC4791]Daboo, C., Desruisseaux, B., and L. Dusseault, "Calendaring Extensions to WebDAV (CalDAV)", RFC 4791, March 2007,<http://www.rfc-editor.org/info/rfc4791>.[RFC4918]Dusseault, L., Ed., "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)", RFC 4918, June 2007,<http://www.rfc-editor.org/info/rfc4918>.[RFC5234]Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, January 2008,<http://www.rfc-editor.org/info/rfc5234>.[RFC5545]Desruisseaux, B., Ed., "Internet Calendaring and Scheduling Core Object Specification (iCalendar)", RFC 5545, September 2009,<http://www.rfc-editor.org/info/rfc5545>.[RFC5546]Daboo, C., Ed., "iCalendar Transport-Independent Interoperability Protocol (iTIP)", RFC 5546, December 2009,<http://www.rfc-editor.org/info/rfc5546>.[RFC6321]Daboo, C., Douglass, M., and S. Lees, "xCal: The XML Format for iCalendar", RFC 6321, August 2011,<http://www.rfc-editor.org/info/rfc6321>.[RFC7265]Kewisch, P., Daboo, C., and M. Douglass, "jCal: The JSON Format for iCalendar", RFC 7265, May 2014,<http://www.rfc-editor.org/info/rfc7265>.[UNICODE.CLDR]The Unicode Consortium, "CLDR calendar.xml Data", Unicode Consortium CLDR,<http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/calendar.xml>.
12.2. Informative References
[ISO.8601.2004]International Organization for Standardization, "Data elements and interchange formats - Information interchange - Representation of dates and times", ISO Standard 8601, December 2004.[UNICODE.ICU]"International Components for Unicode", April 2014,<http://site.icu-project.org>.
Appendix A. xCal RELAX NG Schema Update ๐
okay so the following changes are made to the RELAX NG schema defined in Appendix A of [RFC6321] ๐
# 3.3.10 RECUR
# This extension adds type-rscale and type-skip,
# and modifies type-bymonth
value-recur = element recur {
type-rscale?,
type-freq,
(type-until | type-count)?,
element interval {
xsd:positiveInteger
}?,
type-bysecond*,
type-byminute*,
type-byhour*,
type-byday*,
type-bymonthday*,
type-byyearday*,
type-byweekno*,
type-bymonth*,
type-bysetpos*,
element wkst { type-weekday }?,
type-skip?
}
type-rscale = element rscale {
xsd:string
}
type-bymonth = element bymonth {
xsd:positiveInteger |
xsd:string
}
type-skip = element skip {
"OMIT" |
"BACKWARD" |
"FORWARD"
}
Acknowledgments ๐
thanks to the following for feedback: Mark Davis, Mike Douglass, Donald Eastlake, Peter Edberg, Marten Gajda, Philipp Kewisch, Barry Leiba, Jonathan Lennox, Ken Murchison, Arnaud Quillaud, Dave Thewlis, and Umaoka Yoshito. ๐ซถ
this specification originated from work at the Calendaring and Scheduling Consortium, which has helped with the development and testing of implementations. the real MVPs ๐
Authors' Addresses ๐
Cyrus Daboo
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
United States
EMail: cyrus@daboo.name
URI: http://www.apple.com/
Gregory Yakushev
Google Inc.
Brandschenkestrasse 100
8002 Zurich
Switzerland
EMail: gyakushev@yahoo.com
URI: http://www.google.com/
๐ฆ where this page comes from
- ietf: rfc7529 2015-05
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms