christchurch_django / christchurch /

from dateutil import rrule

def search(calendar, start_date, end_date):
    Searches a vobject calendar for events starting between the specified
    datetime objects, hanlding recurring events as necessary.

    Returns a list of 2 tuples containing (datetime/date of event, vevent object)
    # First, do a pre run to get all the dates we nned to exclude,
    # i.e. those that have specific instances, identified by recurrence-id

    exclusions = []
    for v in calendar.vevent_list:
        rc = v.contents.get('recurrence-id', None)
        if rc is not None:
            # rc is a list, don't know if it can ever contain more than one
            # item, but we'll deal with that anyway.
            for d in rc:

    events = []
    for v in calendar.vevent_list:
        if not hasattr(v, 'rrule'):
            # No recurrence, just look at dtstart
            dt = v.dtstart.value
            if not hasattr(dt, 'date'):
                # A 'date', not 'datetime', can't compare to timezone aware
                # 'datetime'
                if dt >= and dt <=
                    events.append((dt, v))
                if dt >= start_date and dt <= end_date:
                    events.append((dt, v))
            ruleset = rrule.rruleset()
            rule = rrule.rrulestr(v.rrule.value, dtstart=v.dtstart.value)
            if hasattr(v, 'exdate_list'):
                for l in v.exdate_list:
                    for d in l.value:
            for d in exclusions:
            events.extend([(dt, v)
                           for dt in ruleset.between(start_date, end_date)])

    return events