Added support for recurring events
This is a more thorough approach on fetching and parsing recurring events. It has been tested on Google and Yahoo iCalendar, so it might not work on others. As further testing and feedpack is required to test it's reliability, the parsing of reucrring events is switched off by default. Setting 'use_recurring_events' to 'True' activates parsing of recurring events.
This commit is contained in:
parent
d866ee3885
commit
cd6878f8cf
@ -10,13 +10,19 @@ from settings import ical_urls
|
|||||||
import arrow
|
import arrow
|
||||||
from ics import Calendar
|
from ics import Calendar
|
||||||
|
|
||||||
|
use_recurring_events = False ## Attention: experimental feature!
|
||||||
print_events = False
|
print_events = False
|
||||||
style = 'DD MMM YY HH:mm'
|
style = 'DD MMM YY HH:mm'
|
||||||
|
|
||||||
|
|
||||||
|
if use_recurring_events == True:
|
||||||
|
from dateutil.rrule import rrulestr, rruleset
|
||||||
|
import re
|
||||||
|
|
||||||
def fetch_events():
|
def fetch_events():
|
||||||
"""Set timelines for filtering upcoming events"""
|
"""Set timelines for filtering upcoming events"""
|
||||||
now = arrow.now(tz=get_tz())
|
timezone = get_tz()
|
||||||
|
now = arrow.now(tz=timezone)
|
||||||
beginning_of_month = now.replace(days= - now.day +1)
|
beginning_of_month = now.replace(days= - now.day +1)
|
||||||
near_future = now.replace(days= 30)
|
near_future = now.replace(days= 30)
|
||||||
further_future = now.replace(days=40)
|
further_future = now.replace(days=40)
|
||||||
@ -29,6 +35,32 @@ def fetch_events():
|
|||||||
if beginning_of_month <= events.end <= further_future or
|
if beginning_of_month <= events.end <= further_future or
|
||||||
beginning_of_month <= events.begin <= near_future]
|
beginning_of_month <= events.begin <= near_future]
|
||||||
|
|
||||||
|
"""Try to parse recurring events. This is clearly experimental! """
|
||||||
|
if use_recurring_events == True:
|
||||||
|
for ical in calendars:
|
||||||
|
for events in ical.events:
|
||||||
|
event_str = str(events)
|
||||||
|
if re.search('RRULE:(.+?)\n', event_str):
|
||||||
|
if events.all_day and events.duration.days > 1:
|
||||||
|
events.end = events.end.replace(days=-2)
|
||||||
|
else:
|
||||||
|
events.begin = events.begin.to(timezone)
|
||||||
|
events.end = events.end.to(timezone)
|
||||||
|
rule = re.search('RRULE:(.+?)\n', event_str).group(0)[:-2]
|
||||||
|
if re.search('UNTIL=(.+?);', rule) and not re.search('UNTIL=(.+?)Z;', rule):
|
||||||
|
rule = re.sub('UNTIL=(.+?);', 'UNTIL='+re.search('UNTIL=(.+?);', rule).group(0)[6:-1]+'T000000Z;', rule)
|
||||||
|
dates = rrulestr(rule, dtstart= events.begin.datetime).between(after= now.datetime, before = further_future.datetime)
|
||||||
|
|
||||||
|
if dates:
|
||||||
|
duration = events.duration
|
||||||
|
for date in dates:
|
||||||
|
cc = events.clone()
|
||||||
|
cc.end = arrow.get(date+duration)
|
||||||
|
cc.begin = arrow.get(date)
|
||||||
|
upcoming_events.append(cc)
|
||||||
|
#print("Added '{}' with new start at {}".format(cc.name, cc.begin.format('DD MMM YY')))
|
||||||
|
|
||||||
|
|
||||||
"""Sort events according to their beginning date"""
|
"""Sort events according to their beginning date"""
|
||||||
def sort_dates(event):
|
def sort_dates(event):
|
||||||
return event.begin
|
return event.begin
|
||||||
@ -40,9 +72,8 @@ def fetch_events():
|
|||||||
events.end = events.end.replace(days=-2)
|
events.end = events.end.replace(days=-2)
|
||||||
|
|
||||||
if not events.all_day:
|
if not events.all_day:
|
||||||
events.begin = events.begin.to(get_tz())
|
events.begin = events.begin.to(timezone)
|
||||||
events.end = events.end.to(get_tz())
|
events.end = events.end.to(timezone)
|
||||||
|
|
||||||
|
|
||||||
""" The list upcoming_events should not be modified. If you need the data from
|
""" The list upcoming_events should not be modified. If you need the data from
|
||||||
this one, copy the list or the contents to another one."""
|
this one, copy the list or the contents to another one."""
|
||||||
|
Loading…
Reference in New Issue
Block a user