I'm looking for a library (preferably Python, but the language doesn't matter much) that is able to iterate recurring iCal events and handles specific instances automatically.
The iCal file that I'm working with contains recurring events (for example: RRULE:FREQ=WEEKLY;UNTIL=20150614;BYDAY=MO,TU,WE,TH,FR
). These recurring events sometimes have specific instances: the summary might be changed for a single event, or one event is deleted. This result in VEVENT
s in the iCal file with properties like RECURRENCE-ID
and EXDATE
.
Most iCal libraries that I've looked (python-icalendar, ical.js, php iCalCreator) at will help you with the parsing, but will simply return separate (and non-grouped) VEVENT
s for all specific instances. This means you will have to match them to the relevant RRULE
yourself and also determine how this influences the RRULE
.
So, lets assume a recurring event that happens on Monday-Friday from 9:00-10:00. But with a specific instance on Friday (10:00-11:00) and a deleted instance on Wednesday. In this case I would like to iterate the events in a fashion like this:
[
{start: '2015-06-15 09:00:00', end: '2015-06-15 10:00:00'},
{start: '2015-06-16 09:00:00', end: '2015-06-16 10:00:00'},
{start: '2015-06-18 09:00:00', end: '2015-06-18 10:00:00'},
{start: '2015-06-19 10:00:00', end: '2015-06-19 11:00:00'},
]
The Python library recurring-ical-events unfolds events with repetition according the the RFC5455.
pip install recurring-ical-events
Example:
import icalendar
import datetime
import recurring_ical_events
import urllib.request
start_date = (2019, 3, 5)
end_date = (2019, 4, 1)
url = "https://raw.githubusercontent.com/niccokunzmann/python-recurring-ical-events/master/test/calendars/recurring-events-changed-duration.ics"
ical_string = urllib.request.urlopen(url).read()
calendar = icalendar.Calendar.from_ical(ical_string)
events = recurring_ical_events.of(calendar).between(start_date, end_date)
for event in events:
start = event["DTSTART"].dt
duration = event["DTEND"].dt - event["DTSTART"].dt
print("start {} duration {}".format(start, duration))
Output:
start 2019-03-18 04:00:00+01:00 duration 1:00:00
start 2019-03-20 04:00:00+01:00 duration 1:00:00
start 2019-03-19 04:00:00+01:00 duration 1:00:00
start 2019-03-07 02:00:00+01:00 duration 1:00:00
start 2019-03-08 01:00:00+01:00 duration 2:00:00
start 2019-03-09 03:00:00+01:00 duration 0:30:00
start 2019-03-10 duration 1 day, 0:00:00
Old Answer:
From the answer of Sven,
dateutil.rrule claims to handle the rules from ICalendar RFC 5545. If you have a look at the examples, it provides datetime
objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With