iCalendar: Event with multiple dates? - icalendar

I have what I believe to be a nearly minimal calendar with 2 test events:
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:Q1
DTSTAMP:20170504
SUMMARY:Testing Description 1
DTSTART:20170510
DTEND:20170510
DESCRIPTION:Testing Stuff 1
END:VEVENT
BEGIN:VEVENT
UID:Q2
DTSTAMP:20170504
SUMMARY:Testing Summary 1
DTSTART:20170512
DTEND:20170512
DESCRIPTION:Testing Description 1
END:VEVENT
END:VCALENDAR
As you see, the plan is for the 2 events to have the same Summary & Description. That is because I would like it to be a 2-day event.
Does the iCalendar format actually have a proper multi-date event? By multi-date I mean:
not necessarily consecutive dates
multiple dates without a particular pattern (not actually recurring)
I see that iCalendar has quite clever recurrence patterns (http://www.kanzaki.com/docs/ical/rrule.html), but the one thing I can’t find is a rule for arbitrary dates.

To do so, you can have one single VEVENT with DTSTART/DTEND corresponding to the first instance, and an RDATE property with multiple values corresponding to the DTSTART of each of the instances. See https://www.rfc-editor.org/rfc/rfc5545#section-3.8.5.2
An alternative would be to keep two events as you have done, but to link them via a RELATED-TO property: https://www.rfc-editor.org/rfc/rfc5545#section-3.8.4.5
Now, in both cases (especially for RELATED-TO), generic clients may not always understand or take advantage of those properties.

Related

Storing dates as nodes in Neo4j

I'm new to Neo4j so maybe I'm just completely wrong on this, but I'll give it a try!
Our data is mostly composed by reservations, users and facilities stored as nodes.
I need both to count the total reservations that occurred in a specific time frame and the overall income (stored as reservation.income) in this timeframe.
I was thinking to overcome the problem by creating the date as a node, in this way I can assign a relationship [:PURCHASED_ON] to all the reservations that occurred on a specific date.
As far as I've understood, creating the date as a node could give me a few pros:
I could split the date from dd/mm/yyyy and store them as integer properties, in this way I could use mathematical operators such as > and <
I could create a label for the node representing each month as a word
It should be easier to sum() the income on a day or a month
Basicly, I was thinking about doing something like this
CREATE (d:Day {name:01/11/2016 day: TOINT(01), month: TOINT(11), year: TOINT(2016)}
I have seen that a possible solution could be to create a node for every year, every month (1-12) and every day (1-31), but I think that would just complicate terribly the architecture of my Graph since every reservation has an "insert_date" (the day it's created) and then the official "reservation_date" (the day it's due).
Am I onto something here or is it just a waste of time? Thanks!
You may want to look at the GraphAware TimeTree library, as date handling is a complex thing, and this seems to be the logical conclusion of the direction you're going. The TimeTree also has support for finding events attached to your time tree between date ranges, at which point you can perform further operations (counting, summing of income, etc).
There are many date/time functions in the APOC plugin that you should take a look at.
As an example, you can use apoc.date.fields (incorrectly called by the obsolete name apoc.date.fieldsFormatted in the APOC doc) to get the year, month, day to put in your node:
WITH '01/11/2016' AS d
WITH apoc.date.fields(d, 'MM/dd/yyyy') AS f
CREATE (d:Day {name: d, day: f.days, month: f.month, year: f.years});
NOTE: The properties in the returned map have names that are oddly plural. I have submitted an issue requesting that the names be made singluar.

RRULE 20 days after every 15th in a month,in icalendar (RFC 5545)?

I'm searching a way to express a situation like this in icalendar: an event happens every month, x days after a given date.
e.g.: 20 days after 15th day in every month. so, it might be 3rd, 4th, 5th,6th( like February )
if bymonthday can be set to 35, it's ok.
But in outlook this won't work.
How to solve this question?
You could perhaps try adding ";BYSETPOS=20" to the rule. The specification shows an example of BYSETPOS when using it with BYDAY, but it is not clear to me how it is handled when using BYMONTHDAY. I don't see another option looking at the spec.
http://icalendar.org/iCalendar-RFC-5545/3-3-10-recurrence-rule.html
http://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html
Sorry, what you want is not possible with a RRULE.
What you want is RRULE:FREQ=MONTHLY;BYMONTHDAY=35. Unfortunately, it's invalid - BYMONTHDAY can't exceed 31.
BYSETPOS won't work either. In RFC 5545, page 43 under BYSETPOS is the following:
"BYSETPOS operates on a set of recurrence instances in one interval of the recurrence rule."
That means you can't get a value beyond the interval. If you use Monthly you are restricted to the one month.
If you want to experiment with some RRULEs try my recurrence rule (RRULE parser) at
http://balsoftware.net/index.php/open-source/rrule-parser/

How can I exclude DTSTART from generated events if its day not among days specified by BYDAY?

I'm using google-rfc-2445 to generate repeating events according to according to rfc-2445:
The "DTSTART" property for a "VEVENT" specifies the inclusive start of
the event. For recurring events, it also specifies the very first
instance in the recurrence set.
So, for example RRULE for event which occures every Friday 5 times:
DTSTART;TZID=US-Eastern:20160204T090000
RRULE:FREQ=WEEKLY;COUNT=5;BYDAY=FR;INTERVAL=1;
So according to rfc-2445 it will generate 6 events. First event on Thursday 4 February 2016, second event on Friday 5 February 2016, and so on.
How can I achieve that it will exclude first event if it isn't in a pattern? In the example above it should exclude first occurrence, 4 February 2016. In case of defining DTSTART;TZID=US-Eastern:20160205T090000 which is Friday it should leave first occurrence.
Can it be done by defining such "exclusion rule" in RRULE itself or I need to make a check in a code and if DTSTART isn't the same day as defined in BYDAY I should look for closest date in code (manually) and change DTSTART accordingly?
UPDATE
Ok, according to rfc-2445 and this question on google group: https://groups.google.com/forum/#!topic/google-rfc-2445/xqYFe411ysA
The "EXDATE" property can be used to exclude the value specified in
"DTSTART". However, in such cases the original "DTSTART" date MUST
still be maintained by the calendaring and scheduling system because
the original "DTSTART" value has inherent usage dependencies by other
properties such as the "RECURRENCE-ID".
it looks that I need to use EXDATE property to achieve what do I need. Trying to achieve this by following RRULE:
EXDATE;TZID=Asia/Jerusalem:20160210T000000
RRULE:FREQ=WEEKLY;COUNT=5;BYDAY=WE;INTERVAL=1;
And start date is: 2016-02-10T00:00:00.000+02:00 in the following code:
DateTimeIterable dti = DateTimeIteratorFactory.createDateTimeIterable(RRULE, DTSTART, dateTimeZone, true);
But it returns only 4 events, so it always remove first event.
From the description of the problem you give, you will get 6 events when DTSTART is added and you would not want it to be part of the list of instances and 5 events when it is a good date.
So what you want is to only get the last 5 events, which is possible by using the BYSETPOS in your RRULE, the following should do the trick:
BYSETPOS=-5,-4,-3,-2,-1
which will return in all cases the last 5 events that your RRULE gives regardless if the DTSTART is matching the pattern of your RRULE or not.

iCalendar RRULE/RECUR for Thanksgiving weekend?

Is there an "easy" way to create yearly events for "Thanksgiving weekend", meaning an event starting on the 4th Thursday of November (with Sunday as the first weekday), and ending on the following Sunday?
As nearly as I can tell, things like RRULE and RECUR let you create recurring events with zero duration (ie, points in time), but not recurring events that last over a period of time.
What am I missing?
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY:4TH;WKST=SU
You're definitely not restricted to 0 duration events. You can simply specify a DTSTART and DTEND (or DURATION) to get the full weekend.
To elaborate on Evert's answer, to specify a 4 day long event, you just need to specify the DTSTART and DTEND such as below:
DTSTART;VALUE=DATE:20151126 DTEND;VALUE=DATE:20151130 RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=4TH;WKST=SU
the justification comes from below section of RFC5545:
RFC5545 3.6.1The "DTSTART" property for a "VEVENT" specifies the inclusive
start of the event. For recurring events, it also specifies the
very first instance in the recurrence set. The "DTEND" property
for a "VEVENT" calendar component specifies the non-inclusive end
of the event.

How do I make an iCal feed for holidays moved to adjacent weekdays?

I'm trying to make an iCal feed (RFC 2445) for work holidays that won't need yearly updates, by listing holidays per their definition, rather than which dates they occur on on particular years.
Holidays like Memorial day (last Monday in May) of course don't need any special treatment beyond
BEGIN:VEVENT
DTSTAMP:20130210T211949Z
UID:20130210-memorial-day#usa.gov
DTSTART;VALUE=DATE:20130527
DTEND;VALUE=DATE:20130527
SUMMARY:Memorial Day
RRULE:FREQ=YEARLY;BYMONTH=5;BYDAY=-1MO;WKST=SU
END:VEVENT
...but when it comes to date-based holidays like New Year's Day, how does one encode the day slip on weekend Jan 1sts?
you should be aware that even though google calendar follows RFC2445, it has been obsoleted by RFC5545 which has made the EXRULE obsolete (deprecated features from RFC2445).
in the case of UK new year, it is:
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
PRODID:pyICSParser
BEGIN:VEVENT
DTSTART;VALUE=DATE:20070101
RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=MO,TU,WE,TH,FR;BYMONTHDAY=1,2,3;BYSETPOS=1
UID:UIDnewyear_SO14805248#stackeroverflow.com
DTSTAMP:19970714T170000Z
SUMMARY: new year
END:VEVENT
END:VCALENDAR
which works like a charm under google calendar, outlook.com(/hotmail/...), yahoo calendars and on iOS devices synching from a Google Calendar.
UPDATE: for the USA new year
it would be a combination of 2 RRULE (RFC says SHOULD NOT occur more than once which seems to leave the possibility of 2 RRULE by event:
RRULE:FREQ=YEARLY;BYMONTH=1;BYDAY=MO,TU,WE,TH,FR;BYMONTHDAY=1,2;BYSETPOS=1
RRULE:FREQ=YEARLY;BYMONTH=12;BYDAY=FR;BYMONTHDAY=-1
Google Calendar supports it but looks like yahoo and hotmail/outlook.com don't, so 2 events would need to be created (one with each RRULE). If needed the use of RELATED-TO property could help keep track of their relations.
NOTE: The following answer demonstrates how to do it with a deprecated RFC! I am leaving it for reference, in case anyone ever needs to. See the proper answer for more useful facts!
You can do this by adding corresponding yearly repeating adjacent-Friday and adjacent-Monday rules that only show up years where the date has the corresponding weekday:
BEGIN:VEVENT
DTSTAMP:20130210T211949Z
UID:20130210-new-years-day-less-1#usa.gov
DTSTART;VALUE=DATE:20121231
DTEND;VALUE=DATE:20121231
SUMMARY:New Year’s Day (moved from a Saturday)
RRULE:FREQ=YEARLY;BYMONTH=12;BYMONTHDAY=31
EXRULE:FREQ=YEARLY;BYMONTH=12;BYMONTHDAY=31;BYDAY=MO,TU,WE,TH,SA,SU
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20130210T211949Z
UID:20130210-new-years-day-plus-1#usa.gov
DTSTART;VALUE=DATE:20130102
DTEND;VALUE=DATE:20130102
SUMMARY:New Year’s Day (moved from a Sunday)
RRULE:FREQ=YEARLY;BYMONTH=1;BYMONTHDAY=2
EXRULE:FREQ=YEARLY;BYMONTH=1;BYMONTHDAY=2;BYDAY=TU,WE,TH,FR,SA,SU
END:VEVENT
Together with the original event (you can similarly filter this one for BYDAY=MO,TU,WE,TH,FR if you don't want the actual holiday to show up in your feed), you cover all years without getting false positives on years where there was no need to move the time off to a weekday:
BEGIN:VEVENT
DTSTAMP:20130210T211949Z
UID:20130210-new-years-day#usa.gov
DTSTART;VALUE=DATE:20130101
DTEND;VALUE=DATE:20130101
SUMMARY:New Year’s Day
RRULE:FREQ=YEARLY;BYMONTH=1;BYMONTHDAY=1
END:VEVENT
Google Calendar happily consumes and understands my example iCalendar feed. Current iCal (and iOS devices synced from a Google Calendar that imported this feed) unfortunately are a little buggy (filed as  bug 13188350 [link probably only works for the reporter]), and fail to apply the specified weekday filters.
But hopefully that gets fixed too, some time soon.