from datetime import datetime, timedelta, time from dateutil.relativedelta import relativedelta import urllib2 import json import logging import sys import copy from dateutil.rrule import rrulestr import icalendar def fetch_calendar(logger): """Fetches the calendar events and returns a icalendar.Calendar instance. """ response = urllib2.urlopen(CALENDARIUM_IMPORT_URL) logger.debug('Fetched calendar from %s' % CALENDARIUM_IMPORT_URL) return icalendar.Calendar.from_ical(response.read()) def get_events(calendar, after, before): """Yields all events in calendar as dictionary. Only events after (including) after will be shown. Recurring events til before (inclusively) will be shown. """ for event in 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]] = event[fieldinfo[1]].format().encode("utf-8") event_info[fieldinfo[0]] = event_info[fieldinfo[0]].decode("string-escape") except KeyError: event_info[fieldinfo[0]] = fieldinfo[2] start = icalendar.vDDDTypes.from_ical(event['dtstart'].to_ical()) end = icalendar.vDDDTypes.from_ical(event['dtend'].to_ical()) if not isinstance(start, datetime): start = datetime.combine(start, time()) if not isinstance(end, datetime): end = datetime.combine(end, time()) if 'rrule' in event: rrule = rrulestr(event['rrule'].to_ical(), dtstart=start) duration = end - start for occurence in rrule.between(after, before, True): event_info['start'] = occurence event_info['end'] = occurence + duration yield copy.deepcopy(event_info) else: if start >= after: event_info['start'] = start event_info['end'] = end yield event_info class DatetimeEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.isoformat() return json.JSONEncoder.default(self,obj) CALENDARIUM_IMPORT_URL = 'https://sublab.org:5232/calendars/events' if __name__ == '__main__': logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) logger = logging.getLogger('calendar_feed') calendar = fetch_calendar(logger) now = datetime.now() after = now - relativedelta(days=1) before = now + relativedelta(months=+2) events = [] for event in get_events(calendar, after, before): event['start'] = event['start'].isoformat() event['end'] = event['end'].isoformat() events.append(event) print json.dumps(events)