Notes on working with the icalendar spec:http://www.ietf.org/rfc/rfc5545.txt
(RFC2445 spec is obsolete)
More readable format here using old spec: http://www.kanzaki.com/docs/ical/
Briefly: the amr-events plugin creates events as wordpress custom posts. No additional user data is created or stored. The post author (display name and email) is assumed to be the event organiser for purposes of complying with the ics feed RFC5545 standard. The plugins do not send or store data on any other servers.
Collecting & storing of user data:
The amr-events plugin creates events as wordpress posts. As per standard wp processing the author of the post is recorded. That is the extent of any collecting any personal user data that is within the plugins control – only as per standard wordpress user functioning. The plugin does not of itself collect and store user data. Control of that user data rests with the website owner.
Processing or use of user data (email and display name):
This property MUST be specified in an iCalendar object
that specifies a group-scheduled calendar entity. This property
MUST be specified in an iCalendar object that specifies the
publication of a calendar user's busy time.
To conform to this, the event post author’s data is then included in the ics file as per the example in the specification :
The plugin uses the wordpress post authors “display name” if it exists, if not then the wordpress users “userlogin”, and then the wordpress users ‘user_email’ to provide the required ORGANIZER details. The plugin does not have any means to validate this data and simply uses what has been stored the user records by the website.
A web developer can choose to display (or not) the public ics url. The web developer can also control whether a real user or a dummy user is recorded as the post author.
The plugins can also list events from external public ics files. These ics files may contain attendee data. The ics files are cached and refreshed daily or as requested. The cache purpose is to continue to be able to list events should there be a disruption in access to source url. If the web designer chooses to use the addon https://icalevents.com/downloads/amr-events-attendees/ then the web designer can choose to display that attendee data in the event list. That list may be displayed in a public or private page as setup by the web designer. There is currently no provision to add attendee data to the custom events created inside wordpress. If this becomes available, a link to the user data such as the user id or email address is what would be stored.
GDPR Summary
The plugins use a minimal amount of user data required to provide event functionality in adherence with the ‘purpose’ and ‘data minimisation’ principles. With respect to the other GDPR principles, the plugins do not control the accuracy, storage, or security of this user data. The plugin does not pass user data on to any other parties except as required by the RFC5545 ics specification and as configured by the website developer.
Modifications to events, especially to an instance of a recurring event, or an update to a modified instance can all seem quite complex. It’s not that bad once you understand the various bits that you need to provide for the receiving application to make sense of it. See the RFC5545 spec for details. This tools.ietf.org version or icalendar.org or the kanzaki version.
SEQUENCE – numerically update to indicate which is the latest version
RECURRENCE-ID – if modifying a single instance with in a recurring stream. Note that for a UID and SEQUENCE pair, the “RECURRENCE-ID” value for a recurrence instance is fixed. The event date may change but the “RECURRENCE-ID” does not. It must always be the original date as generated by the RRULE.
LAST-MODIFIED – Probably a good idea top update this too
Note also:
if a user subscribes to an ICS URL, then the receiving application will check for updates on a regular basis at a frequency determined by it. It will be seen as a separate calendar. It will use the SEQUENCE numbers to determine the latest event details. There may be a delay in an update being made on the originating system and it being reflected in the receiving system. The only reliable way to be sure that users will have updates seen in their calendars is if you can get them to subscribe to the url (or ‘import’ the url, not the file)
if an ics file is imported (eg: when event details are sent as an ics file attachment, not as a url, or if the user downloads the ics file from a url and then imports it), then it will be added as events into the calendar chosen by the user. Updates may overwrite IF the user re-imports the events AND the application is clever enough to match up the UID’s (and RECURRENCE-IDs if it’s part of a recurring set). It should then also use the SEQUENCE to determine if the details are actually the latest. There is no way on devices to force a user to load an updated ics file sent to them.
Example
Modifications to recurring rules or rdates and modifications to instances of those recurring rules (themselves already a modification.)
Assume we have a recurring event. It starts with a SEQUENCE: 0
This generates an infinite set of mondays, including the following
19th May
16th June
21 July
18 August
etc
Now, one of the instances gets modified. (This could be just the description or the actual date.) A RECURRENCE-ID VEVENT is created for each instance modification and the SEQUENCE NO is updated. The recurrence-id matches the date in the recurring rule that it applies to. The combination of UID, RECURRENCE-ID and SEQUENCE helps us identify the instance that is being updated.
For a given pair of "UID" and "SEQUENCE" property values,
the "RECURRENCE-ID" value for a recurrence instance is fixed.
DTSTART;VALUE=DATE:20140721 (ie no date change in this example)
DTSTAMP:20140720T064853Z
UID:1f4irrb5uh6q3cdfsnq15vd00g_R20140421@google.com
RECURRENCE-ID;VALUE=DATE:20140721
Now assume the original RRULE is modified too, perhaps just the description or shock horror, the recurring date definition? It’s sequence-no is updated too BUT now what should happen to the RECURRENCE-ID instance? Should it be updated to indicate it is still valid? IE we now have:
generated date 21 July 2014 with UID and SEQUENCE = 3 and
RECURRENCE-ID;VALUE=DATE:20140721 with matching UID and SEQUENCE = 3
It appears that perhaps SEQUENCE numbers can increment separately, so one could conceivably receive a file with a RRULE with an equal to or greater sequence number than a RECURRENCE-ID. From this discussion, it is really not clear what the supplying calendar application will do:
Once UID 1/SEQUENCE 0 hits UID 1/SEQUENCE 1 (which would
mean something significant about the set of instances
has changed) all bets are off in regards to RECURRENCE-ID
values that previously existed.
If the UID/RECURRENCE-ID/SEQUENCE matches a generated date from the rrule with same SEQUENCE (ie both have been modified), then what? One cannot just use eg: LAST-MODIFIED:20140620T200327Z. Who is to say that a mod of the RRULE was intended to overwrite the RECURRENCE instance? Quite possibly not.
Some lengthy related discussions here and in other parts of the thread:
Complications that urge one to keep events as simple as possible:
Searching the web seems to indicate some folks believe RECURRENCE-IDS should not change. So should we assume that if the RECURRENCE-ID vevent is still in the file then it is still valid and should be included. (What does this mean for syncing and deletions? IE How does one ‘delete’ an existing event. Or should one always delete events from an ics file and reload ONLY what’s in the ics file?)
There are a number of date and time options for you to choose when displaying your events. The main ones you should be using are created by the plugin and will be formatted by the date and time settings you have specified in the plugin settings (and applying any localisation that may be available in your wordpress setup). You can specify these by listtype, so say a widget could have a very compact date format and a full list may be more detailed.
Event date fields formatted by your date settings:
EventDate: Mon, June 23, 2014
EndDate: Mon, June 30, 2014 (only if event greater than one day)
Event time fields formatted by your time settings:
StartTime: 9:00 am
EndTime: 10:00 am
Note there may be situations where there is no end time or no end date (eg: if there is no duration or the end date is the same as the start date. If a field has not been populated, it will not be displayed and neither will any ‘before’ or ‘after’ text.
Field from the ics specification that may be useful.
Formatted using human language function
DURATION:1 week , 1 hour
Other date fields in the ‘edit events’ admin screen
Last 20140630
The ‘last’ date shown in the edit events admin screen shows the last recurrence date of an event. It is used to select events within a date range (ie exclude events whose recurrences are in the past, without having to rebuild the recurrence logic). It is also used to sort events in the admin screen by this last recurrence. It is therefore formatted yyyymmdd for the sorting. It is not intended to be displayed elsewhere.
Technical fields
These are direct from the ics specification formatted by the DateTime settings in the plugin settings. Note the DTEND has a special definition in the ics specification for all day events (it will have the next day as the end date) and may be confusing to normal users. Some ics generators get the DTEND logic wrong, so this plugin tries to work with duration just in case.
DTEND: Mon, June 30, 2014 10:00 am
DTSTART: Mon, June 23, 2014 9:00 am
Other fields
As these are very technical, precise fields, they are by default not formatted but left as found.
DTSTAMP: 20140616T021842Z
the date and time that the instance of the iCalendar object was created.
LAST-MODIFIED:20140616T025756Z
the date and time last modified – works with the sequence number to determine the latest modification to an event instance.
Some applications will cope with the html, but there are other applications which do not. EG: Google calendar – does not faciliate html nor issue it in feed.
HTML in the description field is not explicitly forbidden, however it is probably not recommended. There is some provision for html to be explicitly allowed for, either:
in the description using an ALTREP parameter,
or in an ‘experiemental’ X field, X-ALT-DESC,
WordPress allows us to create events with html in them. So what to do when the ics feed is generated?
Retaining the html – two possibilties:
Link to the html representation:
DESCRIPTION;ALTREP="http://www.example.com/somepath/":This is an example description.
Provide separate field with html representation:
Outlook will recognise:
X-ALT-DESC;FMTTYPE=text/html:<p>This is an example description.</p>
This update does both, as well of course ,as stripping the html from the description field in the ics file. This means images will be stripped too (only for the feed – do not panic!)
If you are using amr-events or amr-ical-events-list you will not have this problem!
Every time a zone somewhere in the world kicks on to daylight saving or off for that matter, I see a bunch of support questions popping up about their event times being off by an hour. (I monitor wordpress support, stackexchange and wpquestions, and maybe a few more…..)
Imagine the confusion this can cause where clients may have subscribed to calendar feeds and have the wrong times.
PHP datetime objects and functions
If people are very lucky, the plugin that they are using has some good coding and is using php DateTime objects with timezone support, and the only problem is that their wordpress timezone is set as a GMT offset, not as a timezone.
That is easily fixed! (goto wordpress general settings)
However all too often the plugin developer has failed to appreciate
the complexities of times around the world,
timezones,
daylight saving and
most importance of managing recurring events in one timezone for a display in another where one zone changes daylight saving. Very easy to generate the wrong times for a recurring event without realising it!
even worse governments sometimes change the date/time of the switchover (ok not that often, but it does happen, and then you hope your php installation gets updated with the timezone definitions)
Fixes:
If it is not a simple wordpress timezone setting, then these things are NOT easy to fix and will involve changes to code:
Change to use php DateTime Classes for all date logic .If they are using unix time and not php datetime objects, it is almost impossible to get it right. It’s a fairly major rewrite to change all date logic to use the DateTime objects and functions.
If already using, it maybe that the intricacies of recurring event logic have won out. See below for logic help.
Developers and event website managers should read:
The ical specification allows one to define some very interesting and complicated date recurrences. This table (adapted from rfc-archive.org/getrfc.php?rfc=5545) was very useful when I decided to rewrite the recurrence engine part of my plugins.
Sorry about the table width – got to get that theme css fixed!
Yearly
Monthly
Weekly
Daily
Hourly
Minutely
Secondly
BY MONTH (1 to 31, -1 to -31)
Expand
Limit
Limit
Limit
Limit
Limit
Limit
BY WEEK NO (1 to 53, -1 to 53)
Expand
invalid
invalid
invalid
invalid
invalid
invalid
BY YEAR DAY (1 to 366, -1 to -366)
Expand
invalid
invalid
invalid
Limit
Limit
Limit
BY MONTH DAY (1 to 31, -1 to -31)
Expand
Expand
invalid
Limit
Limit
Limit
Limit
BY DAY (MO, TU , WE, TH, FR, SA, SU)
Note 2
Note 1
Expand
Limit
Limit
Limit
Limit
BY HOUR (-23 to 0 to +23)
Expand
Expand
Expand
Expand
Limit
Limit
Limit
BY MINUTE (-59 to 0 to 59)
Expand
Expand
Expand
Expand
Expand
Limit
Limit
BY SECOND (-60 to 0 to 60)
Expand
Expand
Expand
Expand
Expand
Expand
Limit
BY SET POS (-366 to -1,1 to 366)
Limit
Limit
Limit
Limit
Limit
Limit
Limit
The “By”‘s are applied in the order indicated. Limit means that the possible repeat dates are limited by the “BY” specification. Expand means that the possible repeat dates are expanded by the BY values. The start date will fill in any missing year, month, day, hour, minute or second values. See the RFC 5545 Specification for examples.
Note 1:
Limit the dates if BYMONTHDAY is present;
else special expand for monthly
Note2:
Limit if BYYEARDAY or BYMONTHDAY is present; otherwise,
special expand for WEEKLY if BYWEEKNO present; otherwise,
special expand for MONTHLY if BYMONTH present; otherwise,
daylight saving time definitions with a series of daylight saving transitions (as rules have changed over time
Ideally every system around the world should be using the same definition of timezones. However not all systems are kept up to date when a government decides to change a transition time. In addition not all systems use the same naming conventions, so while to the human it may be obvious which timezone is being referred to, a program has to do some deductions.
Most calendar applications appear to use the olson database or similar. Windows PC take a slightly different approach, with a requested time change on the first reboot after daylight saving change. Windows based application issue different timezone ID’s.
A calendar application can decide on it’s own timezone id’s. They have to include the definition (The VTIMEZONE) with the daylight saving changes in the file, however this can be their own version of the timezone definition
Recently I dealt with an ics file that had no TZID, no VTIMEZONE, all dates local / floating
Microsoft Windows PC, Microsoft Exchange
Microsoft exchange, Windows PC’s and by extension any application that runs on the PC that uses the windows timezones does the gmt offset thing
(GMT+10:00) Canberra, Melbourne, Sydney.
Now Sydney has daylight saving, so we are only GMT+10 for half the year. The rest of the time we are GMT+11. If we happen to choose the GMT+11 option for our setup thinking it was more correct we would be wrong…..
What windows does is technically not wrong. They acknowledge the daylight saving and you can choose to have it automatically update… WHEN you REBOOT the PC, the times will update.
It is however potentially misleading, unnecessarily so. Particularly around the actual daylight saving change, errors may occur, due
an ‘old’ ics file perhaps – the one issued before the times were updated ?, or
to applications not always handling the timezone correctly – It would be very tempting as a programmer to grab that GMT+10 and use that. Just google things like my meeting is one hour out etc to get a feeling for the problem.
What does this mean for developers using calendar files?
Well it depends a bit on the application issuing the ics file. You could have to deal with any of these timezone values:
This is correct according to the spec and not too hard to deal with. The developer can grab each city and check for a matching timezone on their host system.
A minor gripe is that if you import this into Google and then share the resulting google calendar file, Google will decide to go with Melbourne, even if the rest of your calendars are Sydney. This may offend some. ;-)
DTSTART;TZID="(GMT+01.00) Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna":20100831T160000
I don’t know whether a VTIMEZONE was included or not. AS noted before grabbing that GMT+01 may cause incorrect times when daylight saving is involved.
At the very least the reading application has to deal with that somehow. Possibly by tossing the GMT parts away and looking for the cities again. My events plugin will do this in the next upgrade
Mozilla / Thunderbird
Mozilla plays nicely (with php anyway!)
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Australia/Sydney
...
DTSTART;TZID=Australia/Sydney:20100901T170000
Reading the VTIMEZONE definition?
Somehow working with the timezone definition passed in the ics file – Is this an option ? – well maybe – I shudder to think how though. Imagine the confusion if some dates in your website knew about one set of daylight saving and others were obeying the possibly different definition in the ics file. PHP encourages us to use it’s timezone definitions. It has functions to do a variety of timezone functions, but uploading daylight saving changes into a timezone object is not one of them. (Probably a good idea too).
Parsing Timezone Ids
If you are developing an ical parser, I believe that the best approach (wrt correctness and usability) is
attempt to determine the desired timezone from the TZ id (toss those GMT’s if you have too)
match to a timezone identifier that is already in your system, and then use those consistent daylight saving changes
and of course use the DateTime object class – do not mess around with unix time that breaks on old dates.
Dates, Times, Timezones, daylight saving etc are so fraught with danger (see the best of dates, the worst of dates), that one must use pre-tested logic as much as possible, and there are some very useful functions there.
My amr-ical-events-list plugin
For the record, my plugin will attempt to cope with all of these variations (and more if anyone tells me about them). If we can extract some city names, it should be easy to match it at least one to the php timezones:
explode the names out, stripping off all the quotes, slashes etc
If a timezone has been specified in the shortcode, and it matches the city name, then it will deduce that is the timezone
If the wordpress timezone matches the city name, then it will deduce that that is the timezone
Else if will attempt to find a match in the php timezone names list (which it should unless something really weird is going on)
Else if all that fails, it will just use the wordpress timezone as the base timezone for the events.
Extract From http://tools.ietf.org/html/rfc5545
This property parameter specifies a text value that uniquely identifies the “VTIMEZONE” calendar component to be used when evaluating the time portion of the property. The value of the “TZID” property parameter will be equal to the value of the “TZID” property for the matching time zone definition. An individual “VTIMEZONE” calendar component MUST be specified for each unique “TZID” parameter value specified in the iCalendar object.
…
Failure to include and follow VTIMEZONE definitions in iCalendar objects may lead to inconsistent understanding of the local time at any given location
The presence of the SOLIDUS character “/” as a prefix, indicates that this “TZID” represents a unique ID in a globally defined time zone registry (when such registry is defined).
Note: This document does not define a naming convention for time zone identifiers. Implementers may want to use the naming conventions defined in existing time zone specifications such as the public-domain TZ database [TZDB]. The specification of globally unique time zone identifiers is not addressed by this document and is left for future study.
ByYearDay allows the user to enter days of the year to repeat separated by commas (1,2,…366,-366,-365…-1). Almost every real example can be represented in a more user friendly fashion using other ‘BY’s such as BYMONTH and BYMONTHDAY
An example: RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU;BYYEARDAY=72
Only leap years affect whether the 72nd day of the year is 31+28+13 = March 13 or 31+29+12 = March 12. It’s just not useful enough to schedule a meeting on “March 13, except March 12 if it’s a leap year” and that kind of use case can be worked around. (One special case might be to state that a RRULE that occured yearly on Feb 29 might automatically recur on Feb 28 if not a leap year). Without BYYEARDAY we’d see rules like “RRULE:FREQ=YEARLY; INTERVAL=1” and the date would be March 12 every year.
For this reason, at launch, the amr events plugin does not offer a BYYEARDAY entry option on the edit event screen. It will however read BYYEARDAY’s entered in ics files and apply the necessary recurrence rule and included in any calendar listing.
Does your group need BYYEARDAY ?
If your website needs to be able to offer entry of recurring dates using BYYEARDAY for it’s members, it will be easy to add. It is beingexcluded to avoid cluttering the screen unnecessarily.
According to wikipedia,the last week of the ISO week-numbering year is the week before week 01; in accordance with the symmetry of the definition, equivalent definitions are:
* the week with the year’s last Thursday in it
* the week ending with the Sunday which is nearest in time to 31 December
* the week with December 28 in it
* the last week with the majority (four or more) of its days in the ending year
* the week starting with the Monday in the period 22 – 28 December
* the week with the Thursday in the period 25 – 31 December
* the week ending with the Sunday in the period 28 December – 3 January
* If 31 December is on a Monday, Tuesday, or Wednesday, it is in week 01 of the next year, otherwise in week 52 or 53.
So this plugin when calculating the weekno and if there is a WKST specification in the rule, uses “the week with December 28 in it” to calculate the last week and handle negative BYWEEKNO’s that way.
Week numbers and BYWEEKNO and weeks start with Monday, Sunday, Saturday (WKST)
How the week number is entered and sent in an ics file is important in two areas of this events plugin.
For communication with other calendar systems, one must stick to the ical RFC5545 (ie : ISO 8601) definition so that recurring dates will be accurately reflected.
For listing of events (agenda or calendar style) however there may be expectations of other week numberings (For example many timeshare resorts use very different week numbering systems, depending on when “their” weeks start – eg: Friday, Saturday, Sunday.) It is simply not possible to cope with all of these, at this stage . The RFC5545 spec (see below) implies that one can combine BYWEEKNO and WKST to give some flexibility. The amr events plugin will pick up the week start defined in your wordpress website.
What does the plugin do wrt week numbers ?
When entering a week number, the ISO8601 in combination with the weekstart (WKST ) will be expected. To aid data entry, it will be checked against the start date (which must be in the week number) and the error message will tell you the wek number of the start date.
At launch, the listing plugin is limited to using the PHP functions for calculating the week number.
which day the week starts on (Monday, Sunday, Saturday, Wednesday (Hungary?)), but also
what defines where one begins in the year with partial weeks or full weeks
Week containing Jan 1 (Eastern European, India, Arabic countries, Canada, China etc..)
Week containing Jan 4 (European countries)
Week containing Jan 7 & Monday (Eastonia and Pakistan)
A list of these is available at pjh2.de and more information from JR Stockton
Technical Definitions of BYWEEKNO
From the RFC5545 Specification:
The BYWEEKNO rule part specifies a COMMA-separated list of ordinals specifying weeks of the year. Valid values are 1 to 53 or -53 to -1. This corresponds to weeks according to week numbering as defined in [ISO.8601.2004]. A week is defined as a seven day period, starting on the day of the week defined to be the week start (see WKST). Week number one of the calendar year is the first week that contains at least four (4) days in that calendar year. This rule part MUST NOT be used when the FREQ rule part is set to anything other than YEARLY. For example, 3 represents the third week of the year.
Note: Assuming a Monday week start, week 53 can only occur when Thursday is January 1 or if it is a leap year and Wednesday is January 1.
This note from aspose.com advises: Use BYWEEKNO only when conformance with ISO 8601 is required. Week numbers as defined by ISO 8601 are very different from week numbers in “common” sense. According to ISO 8601, week number one of the calendar year is the first week of a calendar year that contains at least four days. This rule makes the algorithm specific to applications requiring conformance to ISO 8601 and make it almost inapplicable to other “normal” uses.
ISO 8601 is supported by some European banking and financial applications. It is also used in Television for booking commercials. An ISO week calculator can be found at http://www.personal.ecu.edu/mccartyr/isowdcal.html
The BYWEEKNO rule specifies a comma-delimited list of numbers identifying weeks of the year. Valid values are 1 to 53 and 1 to 53. This corresponds to weeks according to week numbering as defined in ISO 8601. BYWEEKNO is only valid for YEARLY rules.
To illustrate, the following are two very different recurrence patterns:
Friday of 1st ISO 8601 week of the year: FREQ=YEARLY;BYWEEKNO=1;BYDAY=FR
1st Friday of the year : FREQ=YEARLY;BYDAY=1FR
In 1999, for example, 1st Friday of the year is 1999/01/01, while Friday of the 1st ISO 8601 week is 1999/01/08.