lpil / icalendar

🗓️ A small library for reading and writing ICalendar files.
MIT License
103 stars 56 forks source link

Calculating Occurrences #5

Open johnhamelink opened 8 years ago

johnhamelink commented 8 years ago

Hi there,

I/we will be looking to port some ruby code which made use of the ice_cube gem in the near future. I thought before we begin working on PRs for this repo we'd check to see if you have any thoughts on the following bits of functionality we plan to implement in order to port over successfully:

Do you have any advice / tips / etc with regards to how this stuff gets implemented that will make sure we have a higher chance of getting merged? Any thoughts on how you'd implement these features?

Best JH

lpil commented 8 years ago

Hey JH

I'm very open to PRs, thanks for the help. DateTime support would be fantastic.

As for the other features, they sound like good additions. It'd be nice to have an issue opened that detailed what sort of API you'd have for this feature before you implement it. :)

Cheers, Louis

johnhamelink commented 8 years ago

Calculating Occurrences

I've been doing some research into how other libraries such as ice_cube handle the production of occurrences.

Based on my research I will present my opinions on what we should do to implement the occurrences correctly.

Intervals

In order to build occurrences, we need to build logic to understand the interval between each occurrence. This should be calculated in a certain order - from smallest differentiator (second) to largest (year).

DURATION Property

I believe we'll need to support the Duration property. This will allow us to establish for how long an occurence will last. This will be used when calculating the intervals.

VTIMEZONE Property

From the iCal spec on RRULE:

The "DTSTART" and "DTEND" property pair or "DTSTART" and "DURATION" property pair, specified within the iCalendar object defines the first instance of the recurrence. When used with a recurrence rule, the "DTSTART" and "DTEND" properties MUST be specified in local time and the appropriate set of "VTIMEZONE" calendar components MUST be included. For detail on the usage of the "VTIMEZONE" calendar component, see the "VTIMEZONE" calendar component definition.

In order to ensure RRULEs are generated with the correct timezone, it's important we support VTIMEZONE in order to serialize and deserialize RRULE's UNTIL property correctly. Currently we assume that the UNTIL property is in UTC.

Windows of interest

We should count forward from a certain point in time to the window of time that we're interested in, only recording the time periods which we've marked as interesting. It'd be cool to investigate further the viability of using Streams to build a module to handle this lazily.

If DTSTART is set, we should begin iterating from that point. If it's not set, then we should begin from Timex.now.

lpil commented 8 years ago

Heya

I'm having a little trouble understanding exactly what this feature is. Could you step back a little and explain occurrences and their usage? Currently it feels out of the scope of this (de)serialisation library to actually calculate them.

johnhamelink commented 8 years ago

@lpil you may be right that it's out of scope - I'll leave the final call on that to you.

DTSTART and DTEND provide the initial timstamps for the initial occurrence of an event. An RRULE then defines the pattern that is applied to DTSTART and DTEND to get the subsequent events following it. What I'm looking to build is the logic that allows the calculations to be made which follow the RRULE pattern in order to figure out things like when the next event occurrence will be after a given timestamp, what occurrences will happen within a timeframe, or whether two events overlap.

If we agree that it is out of scope, I can always create an ICalendar.RRULE library which is designed to be compatible with this one.

lpil commented 8 years ago

This seems like the kind of functionality that would be very handy to have outside of the context of ics files. Let's make it another project, and we can add it as a dep or plugin if desired.

walter commented 7 years ago

Just noting here that I found a lib that's made a start on calculating occurrences based on RRULE:

https://github.com/alaister/elixir_rrule/blob/master/lib/RRule.ex # after line 45

Reviewing for my short term needs now and seeing if there is anything worthy of rolling into our work.

walter commented 7 years ago

Here's another implementation I'm reviewing:

https://github.com/fazibear/ex_ical/blob/master/lib/ex_ical/recurrence.ex

walter commented 6 years ago

I've finally extracted my work on this so that it can be public!

Work-in-progress at https://github.com/walter/icalendar_event_occurrence

lpil commented 6 years ago

Great! Should we link this from the README?

walter commented 6 years ago

It has a dependency on RRULE implementation being in place, so I think adding it to the README from within the feature/rrule branch PR makes sense.

ericdude4 commented 4 years ago

I have added RRULE deserializing to my PR https://github.com/lpil/icalendar/pull/43. I also tweaked and added the recurrence module from https://github.com/lpil/icalendar/issues/5#issuecomment-265347768 as a convenience tool. Simply run ICalendar.Recurrence.add_recurring_events([%Event{} | _], end_date \\ DateTime.utc_now()) and the recurrences will get added to the list of events.