import urllib2 import icalendar from dateutil.rrule import rrulestr class Event(object): def __init__(self, name, description, start, end): self.name = name self.description = description self.start = start self.end = end def __repr__(self): return '<%s.%s (name=%s, start=%s, end=%s)>' % ( __name__, self.__class__.__name__, repr(self.name), repr(self.start), repr(self.end)) class Calendarium(object): def __init__(self, string): """ Loads a calendar from the string and provides a nice API to it. """ self.calendar = icalendar.Calendar.from_string(string) def get_events(self, after, before): """ This functions yields a list of events in the calendar. Only events after (including) after will be shown. Recurring events til before (inclusively) will be shown. """ for event in self.calendar.walk('vevent'): event_fields = [ # dest , src, default ('name', 'summary', 'unknown Event'), ('description', 'description', ''), ] event_info = {} for fieldinfo in event_fields: try: event_info[fieldinfo[0]] = str(event[fieldinfo[1]]) except KeyError: event_info[fieldinfo[0]] = fieldinfo[2] start = icalendar.vDatetime.from_ical(event['dtstart'].ical()) end = icalendar.vDatetime.from_ical(event['dtend'].ical()) if 'rrule' in event: rrule = rrulestr(event['rrule'].ical(), dtstart=start) duration = end - start for occurence in rrule.between(after, before, True): yield Event( start=occurence, end=occurence + duration, **event_info) else: if start >= after: yield Event(start=start, end=end, **event_info) if __name__ == '__main__': # simple example from dateutil.relativedelta import relativedelta from datetime import datetime import urllib2 calendar_request = urllib2.urlopen('https://sublab.org:5232/calendars/events') calendar = Calendarium(calendar_request.read()) calendar_request.close() now = datetime.now() events = list(calendar.get_events(now-relativedelta(days=1), now+relativedelta(months=+2))) events.sort(key=lambda x:x.start) for event in events: print event