Beispiel #1
0
def parse_tz_posix_env_var(posix_env_var):
    """
	Get the details regarding a timezone by parsing the POSIX style TZ
	environment variable.

	:param str posix_env_var: The POSIX style TZ environment variable.
	:return: The parsed TZ environment variable.
	:rtype: :py:class:`.TimezoneOffsetDetails`
	"""
    match = POSIX_VAR_OFFSET.match(posix_env_var)
    if match is None:
        return
    match = match.groupdict()
    offset = get_timedelta_for_offset(match['offset'])
    if match['offset_dst'] is None:
        offset_dst = None
    elif len(match['offset_dst']):
        offset_dst = get_timedelta_for_offset(match['offset_dst'])
    else:
        # default to an hour difference if it's not specified
        offset_dst = offset - datetime.timedelta(0, SECONDS_IN_ONE_HOUR)
    dst_start = None
    dst_end = None
    match = POSIX_VAR.match(posix_env_var)
    if match:
        match = match.groupdict()
        dst_start = match['start']
        dst_end = match['end']

        match = POSIX_VAR_DST_RRULE.match(dst_start)
        details = match.groupdict()
        byday = details['week'] + DAY_ABBREVIATIONS[int(details['day'])]
        dst_start = icalendar.vRecur({
            'BYMONTH': details['month'],
            'FREQ': 'YEARLY',
            'INTERVAL': 1,
            'BYDAY': byday
        })

        match = POSIX_VAR_DST_RRULE.match(dst_end)
        details = match.groupdict()
        byday = details['week'] + DAY_ABBREVIATIONS[int(details['day'])]
        dst_end = icalendar.vRecur({
            'BYMONTH': details['month'],
            'FREQ': 'YEARLY',
            'INTERVAL': 1,
            'BYDAY': byday
        })
    else:
        # remove the dst offset if not rrule is present on when it's active
        offset_dst = None
    details = TimezoneOffsetDetails(offset, offset_dst, dst_start, dst_end)
    return details
Beispiel #2
0
def makeEvent(term_start, term_end, section, meeting_time, uid):
    event = icalendar.Event()
    event.add('uid', uid)
    event.add('summary',
              '%s %s' % (section['course_code'], section['section']))
    first_day = firstOccurrence(term_start, meeting_time['days'])
    event.add('dtstart', replaceTime(first_day, meeting_time['start']))
    event.add('dtend', replaceTime(first_day, meeting_time['end']))
    event.add('dtstamp', section['user_updated'])
    event.add('categories', 'CLASS')
    rrule = icalendar.vRecur(
        freq='weekly',
        byday=icalDaysOfWeek(meeting_time['days']),
        until=term_end,
    )
    event.add('rrule', rrule)
    descr = io.StringIO()
    descr.write(section['course_name'])
    if 'type' in meeting_time:
        descr.write('\n' + meeting_time['type'])
    if section['instructors']:
        descr.write('\n\nInstructor')
        if len(section['instructors']) > 1:
            descr.write('s')
        descr.write(': ')
        descr.write(', '.join(
            util.name(instr) for instr in section['instructors']))
    event.add('description', descr.getvalue())
    if meeting_time.get('building') or meeting_time.get('room'):
        loc = '%s %s' % (meeting_time.get('building',
                                          ''), meeting_time.get('room', ''))
        event.add('location', loc.strip())
    return event
Beispiel #3
0
def mk_ical(lvinfos, endtimes):
	cal = Calendar()
	cal.add('prodid', '-//swt-ps//python-icalendar//DE')
	cal.add('version', '2.0')
	for uri in lvinfos:
		title,start,end,day,location = lvinfos[uri]
		event = Event()
		event.add('uid', uri)
		start_day = time_conversion.first_day(lvinfos[uri][3][:2])
		shour, sminute = start.split(':')
		ehour, eminute = end.split(':')
		sttime = datetime.datetime(start_day.year, start_day.month,\
					start_day.day, hour = int(shour), minute = int(sminute))
		endtime = datetime.datetime(start_day.year, start_day.month,\
					start_day.day, hour = int(ehour), minute = int(eminute))
		event.add('dtstamp', datetime.datetime.today())
		event.add('summary', title)
		recur = vRecur(byday=biweekly[day][0], freq='weekly',\
					   until=endtimes[uri])
		if biweekly[day][1] == "A":
			if start_day.isocalendar()[1] % 2 == 0:
				sttime = sttime + datetime.timedelta(weeks=1)
				endzeit = endzeit + datetime.timedelta(weeks=1)
			recur['interval'] = 2
		elif biweekly[day][1] == "B":
			if start_day.isocalendar()[1] % 2 == 1:
				sttime = sttime + datetime.timedelta(weeks=1)
				endtime = endtime + datetime.timedelta(weeks=1)
			recur['interval'] = 2
		event.add('dtstart', sttime)
		event.add('dtend', endtime)
		event.add('rrule', recur)
		cal.add_component(event)
	return cal
Beispiel #4
0
def convert(content):
    soup = BeautifulSoup(content)
    entries = [cell.span.text for cell in soup.find_all(name="td", attrs={"class": "allocated"})]

    entries = [filter(lambda x: len(x) > 0, map(lambda x: x.strip(), e.split("\n"))) for e in entries]

    d = datetime.datetime(datetime.date.today().year - 1, 1, 1, tzinfo=pytz.timezone("Europe/Ljubljana"))
    d = d - datetime.timedelta(d.weekday())  # find monday

    cal = Calendar()
    cal.add("prodid", "-//FRiCal//SL")
    cal.add("version", "2.0")

    for e in entries:
        dt_tokens = e[0].split(" ")  # u'sreda 08:00 - 11:00'
        weekday = weekday_names.index(dt_tokens[0])
        time_start = int(dt_tokens[1].split(":")[0])
        time_end = int(dt_tokens[3].split(":")[0])
        d_start = d + datetime.timedelta(days=weekday, hours=time_start)
        d_end = d + datetime.timedelta(days=weekday, hours=time_end)
        summary = "%s; %s" % (e[2], e[1])
        description = "%s\n%s" % (e[3], "\n".join(e[4:]))

        event = Event()
        event.add("dtstart", d_start)
        event.add("dtend", d_end)
        event.add("dtstamp", d)
        event.add("rrule", vRecur(freq="daily", interval=7))
        event.add("summary", summary)
        event.add("description", description)
        cal.add_component(event)

    return cal.to_ical()
 def add_all_saints_eve(self, year):
     """Add recurring event for all saint's eve."""
     event = Holiday(date(year, 1, 1), 'Allhelgonaafton', Work.DEPENDS)
     rrule = vRecur()
     rrule['FREQ'] = vFrequency('YEARLY')
     rrule['BYDAY'] = vWeekday('FR')
     rrule['BYMONTHDAY'] = (30, 31)
     rrule['BYMONTH'] = 10
     event.add('rrule', rrule)
     self.add_component(event)
     event2 = Holiday(date(year, 1, 1), 'Allhelgonaafton', Work.DEPENDS)
     rrule2 = vRecur()
     rrule2['FREQ'] = vFrequency('YEARLY')
     rrule2['BYDAY'] = vWeekday('FR')
     rrule2['BYMONTHDAY'] = (1, 2, 3, 4, 5)
     rrule2['BYMONTH'] = 11
     event2.add('rrule', rrule2)
     self.add_component(event2)
 def add_all_saints_day(self, year):
     """Add recurring event for all saint's day."""
     event = Holiday(date(year, 1, 1), 'Alla helgons dag')
     rrule = vRecur()
     rrule['FREQ'] = vFrequency('YEARLY')
     rrule['BYDAY'] = vWeekday('SA')
     rrule['BYMONTHDAY'] = 31
     rrule['BYMONTH'] = 10
     event.add('rrule', rrule)
     self.add_component(event)
     event2 = Holiday(date(year, 1, 1), 'Alla helgons dag')
     rrule2 = vRecur()
     rrule2['FREQ'] = vFrequency('YEARLY')
     rrule2['BYDAY'] = vWeekday('SA')
     rrule2['BYMONTHDAY'] = (1, 2, 3, 4, 5, 6)
     rrule2['BYMONTH'] = 11
     event2.add('rrule', rrule2)
     self.add_component(event2)
Beispiel #7
0
	def test_parse_tz_posix_env_var_australia_melbourne(self):
		expected = ics.TimezoneOffsetDetails(
			offset=datetime.timedelta(0, 36000),
			offset_dst=datetime.timedelta(0, 32400),
			dst_start=icalendar.vRecur({
				'BYMONTH': '10',
				'FREQ': 'YEARLY',
				'INTERVAL': 1,
				'BYDAY': '1SU'
			}),
			dst_end=icalendar.vRecur({
				'BYMONTH': '4',
				'FREQ': 'YEARLY',
				'INTERVAL': 1,
				'BYDAY': '1SU'
			})
		)
		self.assertParsedTimezoneOffsetDetailsMatch('Australia/Melbourne', expected)
Beispiel #8
0
	def test_parse_tz_posix_env_var_america_new_york(self):
		expected = ics.TimezoneOffsetDetails(
			offset=datetime.timedelta(-1, 68400),
			offset_dst=datetime.timedelta(-1, 64800),
			dst_start=icalendar.vRecur({
				'BYMONTH': '3',
				'FREQ': 'YEARLY',
				'INTERVAL': 1,
				'BYDAY': '2SU'
			}),
			dst_end=icalendar.vRecur({
				'BYMONTH': '11',
				'FREQ': 'YEARLY',
				'INTERVAL': 1,
				'BYDAY': '1SU'
			})
		)
		self.assertParsedTimezoneOffsetDetailsMatch('America/New_York', expected)
Beispiel #9
0
 def test_parse_tz_posix_env_var_australia_melbourne(self):
     expected = ics.TimezoneOffsetDetails(
         offset=datetime.timedelta(0, 36000),
         offset_dst=datetime.timedelta(0, 32400),
         dst_start=icalendar.vRecur({
             'BYMONTH': '10',
             'FREQ': 'YEARLY',
             'INTERVAL': 1,
             'BYDAY': '1SU'
         }),
         dst_end=icalendar.vRecur({
             'BYMONTH': '4',
             'FREQ': 'YEARLY',
             'INTERVAL': 1,
             'BYDAY': '1SU'
         }))
     self.assertParsedTimezoneOffsetDetailsMatch('Australia/Melbourne',
                                                 expected)
Beispiel #10
0
 def test_parse_tz_posix_env_var_america_new_york(self):
     expected = ics.TimezoneOffsetDetails(
         offset=datetime.timedelta(-1, 68400),
         offset_dst=datetime.timedelta(-1, 64800),
         dst_start=icalendar.vRecur({
             'BYMONTH': '3',
             'FREQ': 'YEARLY',
             'INTERVAL': 1,
             'BYDAY': '2SU'
         }),
         dst_end=icalendar.vRecur({
             'BYMONTH': '11',
             'FREQ': 'YEARLY',
             'INTERVAL': 1,
             'BYDAY': '1SU'
         }))
     self.assertParsedTimezoneOffsetDetailsMatch('America/New_York',
                                                 expected)
 def add_midsummer_day(self, year):
     """Add recurring event for the midsummer day."""
     event = Holiday(date(year, 1, 1), 'Midsommardagen')
     rrule = vRecur()
     rrule['FREQ'] = vFrequency('YEARLY')
     rrule['BYDAY'] = vWeekday('SA')
     rrule['BYMONTHDAY'] = (20, 21, 22, 23, 24, 25, 26)
     rrule['BYMONTH'] = 6
     event.add('rrule', rrule)
     self.add_component(event)
Beispiel #12
0
def parse_tz_posix_env_var(posix_env_var):
	"""
	Get the details regarding a timezone by parsing the POSIX style TZ
	environment variable.

	:param str posix_env_var: The POSIX style TZ environment variable.
	:return: The parsed TZ environment variable.
	:rtype: :py:class:`.TimezoneOffsetDetails`
	"""
	match = POSIX_VAR_OFFSET.match(posix_env_var)
	if match is None:
		return
	match = match.groupdict()
	offset = get_timedelta_for_offset(match['offset'])
	if match['offset_dst'] is None:
		offset_dst = None
	elif len(match['offset_dst']):
		offset_dst = get_timedelta_for_offset(match['offset_dst'])
	else:
		# default to an hour difference if it's not specified
		offset_dst = offset - datetime.timedelta(0, SECONDS_IN_ONE_HOUR)
	dst_start = None
	dst_end = None
	match = POSIX_VAR.match(posix_env_var)
	if match:
		match = match.groupdict()
		dst_start = match['start']
		dst_end = match['end']

		match = POSIX_VAR_DST_RRULE.match(dst_start)
		details = match.groupdict()
		byday = details['week'] + DAY_ABBREVIATIONS[int(details['day'])]
		dst_start = icalendar.vRecur({'BYMONTH': details['month'], 'FREQ': 'YEARLY', 'INTERVAL': 1, 'BYDAY': byday})

		match = POSIX_VAR_DST_RRULE.match(dst_end)
		details = match.groupdict()
		byday = details['week'] + DAY_ABBREVIATIONS[int(details['day'])]
		dst_end = icalendar.vRecur({'BYMONTH': details['month'], 'FREQ': 'YEARLY', 'INTERVAL': 1, 'BYDAY': byday})
	else:
		# remove the dst offset if not rrule is present on when it's active
		offset_dst = None
	details = TimezoneOffsetDetails(offset, offset_dst, dst_start, dst_end)
	return details
 def add_midsummers_eve(self, year):
     """Add recurring event for midsummer's eve."""
     event = Holiday(date(year, 1, 1), 'Midsommarafton', Work.DEFACTO)
     rrule = vRecur()
     rrule['FREQ'] = vFrequency('YEARLY')
     rrule['BYDAY'] = vWeekday('FR')
     rrule['BYMONTHDAY'] = (19, 20, 21, 22, 23, 24, 25)
     rrule['BYMONTH'] = 6
     event.add('rrule', rrule)
     self.add_component(event)
	def on_button_ok__clicked(self, *args):
		new_recur = icalendar.vRecur()
		if self.radio_once.get_active():
			new_recur = {}
		elif self.radio_daily.get_active():
			new_recur['FREQ'] = ['DAILY']
			new_recur['INTERVAL'] = [self.spinbutton_daily_interval.get_value()]
		elif self.radio_weekly.get_active():
			new_recur['FREQ'] = ['WEEKLY']
			new_recur['INTERVAL'] = [self.spinbutton_weekly_interval.get_value()]
			byday = []
			if self.checkbutton_weekly_mon.get_active(): byday.append('MO')
			if self.checkbutton_weekly_tue.get_active(): byday.append('TU')
			if self.checkbutton_weekly_wed.get_active(): byday.append('WE')
			if self.checkbutton_weekly_thu.get_active(): byday.append('TH')
			if self.checkbutton_weekly_fri.get_active(): byday.append('FR')
			if self.checkbutton_weekly_sat.get_active(): byday.append('SA')
			if self.checkbutton_weekly_sun.get_active(): byday.append('SU')
			if byday:
				new_recur['BYDAY'] = byday
		elif self.radio_monthly.get_active():
			new_recur['FREQ'] = ['MONTHLY']
			new_recur['INTERVAL'] = [self.spinbutton_monthly_interval.get_value()]
			if self.radiobutton_monthly_recur_mday.get_active():
				bmd_index = self.combobox_monthly_recur_mday.get_active()
				if bmd_index > 30:
					bmd_index = 29 - bmd_index
				bmd_index += 1
				new_recur['BYMONTHDAY'] = [bmd_index]
			elif self.radiobutton_monthly_recur_week.get_active():
				bd_index = self.combobox_monthly_recur_week_nr.get_active()
				if bd_index > 4:
					bd_index = 3 - bd_index
				bd_index += 1
				wd_index = self.combobox_monthly_recur_week_day.get_active()
				new_recur['BYDAY'] = ['%i%s' % (bd_index, weekdays[wd_index])]
		elif self.radio_yearly.get_active():
			new_recur['FREQ'] = ['YEARLY']
			new_recur['INTERVAL'] = [self.spinbutton_yearly_interval.get_value()]
			if self.radiobutton_yearly_recur_dom.get_active():
				new_recur['BYMONTHDAY'] = [self.spinbutton_yearly_recur_dom_nr.get_value()]
				new_recur['BYMONTH'] = [self.combobox_yearly_recur_dom_month.get_active() + 1]
			elif self.radiobutton_yearly_recur_wom.get_active():
				bd_index = self.combobox_yearly_recur_wom_nr.get_active()
				if bd_index > 4:
					bd_index = 3 - bd_index
				bd_index += 1
				dow_index = self.combobox_yearly_recur_wom_dow.get_active()
				new_recur['BYDAY'] = ['%i%s' % (bd_index, weekdays[dow_index])]
				new_recur['BYMONTH'] = [self.combobox_yearly_recur_wom_month.get_active() + 1]
			elif self.radiobutton_yearly_recur_doy.get_active():
				new_recur['BYYEARDAY'] = [self.spinbutton_yearly_recur_doy_nr.get_value()]
		self.recur = new_recur
		self.quit()
Beispiel #15
0
def crearEvento(fe, nom, desc):
    evento = Event()
    time.sleep(
        0.10
    )  # Genero un retardo para que aquellos cumpleaños con misma fecha puedan almacenarse correctamente
    evento.add('summary', 'Cumpleaños de ' + nom)
    evento.add('dtstart', fe)
    evento.add('dtend', fe)
    evento.add('rrule', vRecur(freq='yearly'))
    evento.add('description', desc)
    return evento
Beispiel #16
0
 def icalendar_event(self):
     if self.context.birth_date is None:
         return
     summary = '%s (*%s)' % (icemac.addressbook.interfaces.ITitle(
         self.context), self.context.birth_date.year)
     return icalendar.Event(
         uid=self.url(self.context, 'iCalendar'),
         summary=summary,
         dtstart=icalendar.vDate(self.context.birth_date),
         dtend=icalendar.vDate(self.context.birth_date + ONE_DAY),
         rrule=icalendar.vRecur(freq='yearly'))
Beispiel #17
0
def serialize_repeatability(startDT, endDT, repType):
    intervals = { RepeatabilityEnum.onceAWeek: 1, RepeatabilityEnum.onceEvery2Weeks: 2, RepeatabilityEnum.onceEvery3Weeks: 3 }
    recur = ical.vRecur()
    recur['until'] = endDT
    if repType == RepeatabilityEnum.daily:
        recur['freq'] = 'daily'
    elif repType in intervals.keys():
        recur['freq'] = 'weekly'
        recur['interval'] = intervals[repType]
    elif repType == RepeatabilityEnum.onceAMonth:
        recur['freq'] = 'monthly'
        recur['byday'] = str(weekNumber(startDT)) + WEEK_DAYS[startDT.weekday()]
    return recur
Beispiel #18
0
def serialize_repeatability(startDT, endDT, repType):
    intervals = { RepeatabilityEnum.onceAWeek: 1, RepeatabilityEnum.onceEvery2Weeks: 2, RepeatabilityEnum.onceEvery3Weeks: 3 }
    recur = ical.vRecur()
    recur['until'] = endDT
    if repType == RepeatabilityEnum.daily:
        recur['freq'] = 'daily'
    elif repType in intervals.keys():
        recur['freq'] = 'weekly'
        recur['interval'] = intervals[repType]
    elif repType == RepeatabilityEnum.onceAMonth:
        recur['freq'] = 'monthly'
        recur['byday'] = str(weekNumber(startDT)) + WEEK_DAYS[startDT.weekday()]
    return recur
Beispiel #19
0
def add_timezone(cal):
    cal.add('x-wr-timezone', TZID)
    timezone = Timezone()
    timezone.add('tzid', TZID)
    tz_std = TimezoneStandard()
    tz_std.add('dtstart',
               vText(arrow.get('2006-11-06 02:00').format('YYYYMMDDTHHmmss')))
    tz_std.add('rrule', vRecur(freq='YEARLY', bymonth='11', byday='+1SU'))
    tz_std.add('tzoffsetfrom', timedelta(hours=-4))
    tz_std.add('tzoffsetto', timedelta(hours=-5))
    tz_std.add('tzname', "EST")
    timezone.add_component(tz_std)

    tz_dst = TimezoneDaylight()
    tz_dst.add('dtstart',
               vText(arrow.get('2006-03-13 02:00').format('YYYYMMDDTHHmmss')))
    tz_dst.add('rrule', vRecur(freq='YEARLY', bymonth='3', byday='+2SU'))
    tz_dst.add('tzoffsetfrom', timedelta(hours=-5))
    tz_dst.add('tzoffsetto', timedelta(hours=-4))
    tz_dst.add('tzname', "EDT")
    timezone.add_component(tz_dst)

    cal.add_component(timezone)
Beispiel #20
0
def serialize_repeatability(startDT, endDT, repType):
    intervals = {
        RepeatabilityEnum.onceAWeek: 1,
        RepeatabilityEnum.onceEvery2Weeks: 2,
        RepeatabilityEnum.onceEvery3Weeks: 3,
    }
    recur = ical.vRecur()
    recur["until"] = endDT
    if repType == RepeatabilityEnum.daily:
        recur["freq"] = "daily"
    elif repType in intervals.keys():
        recur["freq"] = "weekly"
        recur["interval"] = intervals[repType]
    elif repType == RepeatabilityEnum.onceAMonth:
        recur["freq"] = "monthly"
        recur["byday"] = str(weekNumber(startDT)) + WEEK_DAYS[startDT.weekday()]
    return recur
Beispiel #21
0
def kurzusize(nap, darabos, hely, kurzus):
    event = Event()
    event.add("summary", kurzus)
    # 0: vasárnap, hogy könnyen tudjuk felpakolni az első hétre az eseményeket.
    # darabos óra + 1? időzóna, my friend. utc-ben dolgozunk, mert különben kéne időzónát gyártani,
    # viszont errefelé utc+1/utc+2 van. szerencsére nem kavar be a márciusvégi időszámítás-váltás,
    # a hozzáadáskori időzónához igazodik a kliens, ha jól nézem.
    hozzaadando = ahetnapjai.index(nap)
    event.add("dtstart", datetime(2010, 2, 7 + hozzaadando, darabos[0] - 1, darabos[1], 0, tzinfo=UTC))
    event.add("dtend", datetime(2010, 2, 7 + hozzaadando, darabos[2] - 1, darabos[3], 0, tzinfo=UTC))
    event.add(
        "dtstamp", datetime(2010, 1, 29, 0, 10, 0, tzinfo=UTC)
    )  # "mikor adták hozzá vagy módosították az eseményt". lényegtelen, de kell.
    event.add("location", hely)
    recur = vRecur(freq="weekly", byday=nap, count=15)  # kézzel számoltam, vigyázz!
    event.add("rrule", recur)
    return event
Beispiel #22
0
def icalevent(e):
    if not all(prop in e for prop in ['date', 'title']):
        return
    iev = Event()
    iev.add('dtstamp', datetime.now())
    iev.add('dtstart', e['date'])
    iev.add('dtend', e['date'] + timedelta(1))
    rrule = vRecur()
    rrule['freq'] = vFrequency('yearly')
    iev.add('rrule', rrule)
    iev.add('summary', vText("{:04d}: {}".format(e['date'].year, e['title'])))
    iev.add('uid', "{}@icalaniversary.invalid".format(slugify(iev['summary'])))
    desc = [e.get('link'), e.get('desc')]
    if any(desc):
        desc = "\n".join([x for x in desc if x])
        iev.add('description', vText(desc))
    return iev
Beispiel #23
0
def build_calendar(daily_events, day2abrev, day2key, code2name, end_date, repeat):

    end_grad = datetime.datetime.strptime(end_date, '%Y-%m-%d')


    cal = Calendar()

    now = datetime.datetime.now()
    year = now.year
    month = now.month
    weekday = now.day

    days_left = end_grad - now
    if not repeat:
        weeks_left = int(days_left.days / 7) + 1
    else:
        weeks_left = int(repeat) + 1

    for day, events in daily_events.items():
        next_day = now + datetime.timedelta(days=(day2key[day] - now.weekday()) % 7)
        next_day = next_day.day
        for ev in events:
            if ev:
                event = Event()
                begin = ev[0][0]
                end = ev[0][1]
                description = ev[1].split("-")[0]
                title = code2name[description]
                place = ev[2]
                event.add('summary', title)
                event.add('location', place)
                event.add('description', description)
                begin_hour, begin_minute = begin.split(":")
                end_hour, end_minute, end_second = end.split(":")

                event.add('dtstart', datetime.datetime(year, month, next_day, \
                          hour=int(begin_hour), minute=int(begin_minute)))
                event.add('dtend', datetime.datetime(year, month, next_day,  \
                          hour=int(end_hour), minute=int(end_minute)))
                event['RRULE'] = vRecur({'COUNT': [weeks_left], \
                                        'FREQ': ['WEEKLY'], \
                                        'BYDAY': day2abrev[day]})
                cal.add_component(event)
    return cal
    def addEvent(self, node, date):
        strings = node.findAll(text=True)
        event = Event()

        event.add("summary", strings[0])

        match = re.search("(\d\d?:\d\d [ap]m)-(\d\d?:\d\d [ap]m)", strings[2])
        if match is None:
            print >> stderr, "Warning: Could not parse time string, %s" % strings[2]
            return False
        else:
            event.add("dtstart", datetime.strptime(date + match.group(1), "%Y-%m-%d %I:%M %p"))
            event.add("dtend", datetime.strptime(date + match.group(2), "%Y-%m-%d %I:%M %p"))
        if self.enddate is not None:
            recur = vRecur(freq="WEEKLY", until=self.enddate)
            event.add("rrule", recur, encode=0)

        event.add("location", strings[3])

        self.calendar.add_component(event)
Beispiel #25
0
    def add_event(self, ev):
        """
        Add a new recurrent event to this schedule
        """
        day = self._get_first_weekday(ev.day)
        dtstart = datetime.combine(day, ev.tstart)
        dtend = datetime.combine(day, ev.tend)

        tz_params = {'tzid': 'Europe/Paris'}

        iev = Event()
        iev.add('uid', str(uuid4()))
        iev.add('status', 'confirmed')
        iev.add('dtstart', dtstart, parameters=tz_params)
        iev.add('dtend', dtend, parameters=tz_params)
        iev.add('rrule', vRecur(self._recur_params(ev.day)))
        iev.add('summary', '%s %s' % (ev.type_, ev.title))
        iev.add('location', ev.room)
        iev.add('description', ev.description)
        self.cal.add_component(iev)
Beispiel #26
0
    def fill_term(self, schedule, term):
        parser = PeriodParser(schedule['year'], term)

        for evt in schedule[term]:
            vevt = Event()
            dtstart, dtend = parser.parse(evt)
            vevt.add('dtstart', dtstart)
            vevt.add('dtend', dtend)

            # set info
            vevt.add('summary', evt['summary'])
            vevt.add('description', evt['description'])

            # set RRULE
            rec = vRecur()
            rec['FREQ'] = 'WEEKLY'
            rec['BYDAY'] = evt['weekday']
            rec['UNTIL'] = parser.eot
            vevt.add('RRULE', rec)

            self.ical.add_component(vevt)
Beispiel #27
0
def create_events(
    first: date,
    last: date,
    excludes: List[date],
    timetable: List[Tuple[str, List[int], time, time, str]],
) -> Iterator[icalendar.Event]:
    for summary, days, start, end, location in timetable:
        event = icalendar.Event()
        first_day = get_first_day(first, days)
        event.add("DTSTART", datetime.combine(first_day, start))
        event.add("DTEND", datetime.combine(first_day, end))
        event.add("SUMMARY", summary)
        event.add("LOCATION", location)
        recur = icalendar.vRecur()
        recur["FREQ"] = "WEEKLY"
        recur["UNTIL"] = datetime.combine(last, end)
        recur["BYDAY"] = list(map(DAYS.get, days))
        event.add("RRULE", recur)
        for exclude in excludes:
            event.add("EXDATE", datetime.combine(exclude, start))
        yield event
Beispiel #28
0
    def as_ical(self, description=None, rrule=None, url=None):
        """ Returns the occurrence as iCalendar string. """

        event = icalendar.Event()
        event.add("summary", self.title)
        event.add("dtstart", to_timezone(self.start, UTC))
        event.add("dtend", to_timezone(self.end, UTC))
        event.add("last-modified", self.modified or self.created or datetime.utcnow())
        event["location"] = icalendar.vText(self.location)
        if description:
            event["description"] = icalendar.vText(description)
        if rrule:
            event["rrule"] = icalendar.vRecur(icalendar.vRecur.from_ical(rrule.replace("RRULE:", "")))
        if url:
            event.add("url", url)

        cal = icalendar.Calendar()
        cal.add("prodid", "-//OneGov//onegov.event//")
        cal.add("version", "2.0")
        cal.add_component(event)

        return cal.to_ical()
Beispiel #29
0
def lesson_as_ical_event(lesson, lesson_date, timetable):
    event = Event()
    event.add('uuid', lesson_uuid(lesson))
    event.add('summary', lesson.subject)
    addr = vCalAddress('MAILTO:[email protected]')
    addr.params['CN'] = lesson.tutor.encode('utf-8')
    event['organizer'] = addr
    event.add('location', lesson.auditory)
    event.add('rrule', vRecur({'freq': 'WEEKLY', 'interval': 2}))

    start_time = timetable.start(lesson.number)
    end_time = timetable.end(lesson.number)

    event['dtstart'] = vDatetime(
        datetime(lesson_date.year, lesson_date.month,
                 lesson_date.day, start_time.hour, start_time.minute,
                 tzinfo=start_time.tzinfo))
    event['dtend'] = vDatetime(
        datetime(lesson_date.year, lesson_date.month,
                 lesson_date.day, end_time.hour, end_time.minute,
                 tzinfo=end_time.tzinfo))

    return event
Beispiel #30
0
def genICal(data, modCode, index):
    cal = icalendar.Calendar()
    cal.add('prodid', '-//NTUmodswap bot//')
    cal.add('version', '2.0')
    cal.add('method', 'PUBLISH')

    for i in data[index]:
        event = icalendar.Event()
        event.add('summary', modCode + " " + i.type)
        event.add('location', i.loc)
        if i.type == "TUT":
            event.add(
                'dtstart',
                timedelta(days=7) +
                transformTime(i.day, int(i.time[0:2]), int(i.time[2:4])))
            event.add(
                'dtend',
                timedelta(days=7) +
                transformTime(i.day, int(i.time[5:7]), int(i.time[7:9])))
        else:
            event.add('dtstart',
                      transformTime(i.day, int(i.time[0:2]), int(i.time[2:4])))
            event.add('dtend',
                      transformTime(i.day, int(i.time[5:7]), int(i.time[7:9])))
        event.add('dtstamp', datetime.now())
        event.add('rrule', icalendar.vRecur({
            "FREQ": "WEEKLY",
            "UNTIL": semEnd
        }))
        event.add(
            'exdate',
            transformTime(i.day, int(i.time[0:2]), int(i.time[2:4]), recess))
        cal.add_component(event)

    # print(str(cal.to_ical()))
    return cal.to_ical()
 def rrule(self):
     byweekday = '+{}{}'.format(self.week, dateutil.rrule.weekday(self.day_of_the_week))
     return icalendar.vRecur(freq='MONTHLY', interval=self.skip_months + 1,
                     byday=byweekday)
Beispiel #32
0
        start_date = datetime.datetime.strptime(
            (date["start_date"]), "%Y-%m-%d") + d
        end_date = datetime.datetime.strptime(
            (date["end_date"]), "%Y-%m-%d") + d

        start_hour = datetime.timedelta(hours=ev['start_time'])
        duration = datetime.timedelta(hours=int(ev['duration']))

        start_date_time = (start_date + start_hour)
        end_date_time = (start_date_time + duration)

        event = Event()
        event.add('summary', ev['title'])
        event.add('location', ev['location'])

        recur = vRecur(FREQ='weekly', UNTIL=end_date)
        event.add('rrule', recur)

        event.add('dtstart', start_date_time)
        # Add an extra day as RFC2445 appears to suggest that is the correct way,
        # and that's the way Google Calendar treats it
        event.add('dtend', end_date_time)
        event.add('class', 'PUBLIC')

        cal.add_component(event)

sys.stdout.write(cal.to_ical())
# should validate at http://icalvalid.cloudapp.net/
import dateutil.parser
import datetime, time
import scraperwiki
    startdate = date(year, startmonth, startday)
    startWeekday = startdate.weekday()
    delta = 0
    while (startWeekday not in courseStartWeekdays):
        delta += 1
        startWeekday += 1
        if (startWeekday > 6):
            startWeekday = 0

    startdate += timedelta(days=delta)
    
    
    # Make .ics file
    cal = Calendar()
    cal.add('prodid', 'I School Course Calendar')
    cal.add('version', '2.0')
    event = Event()
    event.add('summary', coursetitle)
    event.add('location', course.location)
    event.add('dtstart', datetime(year,startdate.month, startdate.day,starthour,startminute,0))
    event.add('dtend', datetime(year,startdate.month,startdate.day,endhour,endminute,0))
    event.add('tzid', 'California-Los_Angeles')
    finishedt = datetime(year,endmonth,endday,0,0,0)
    event.add('rrule', vRecur(freq='weekly', byday=coursedays, until=finishedt))        
    cal.add_component(event)
    f = open(coursetitle + '.ics', 'wb')
    f.write(cal.as_string())
    print 'Wrote: ' + coursetitle + '.ics'
    f.close()
 def rrule(self):
     return icalendar.vRecur(freq='MONTHLY', interval=self.skip_months + 1,
                             bymonthday=self.date)
 def __init__(self, dtstart, summary, work=Work.FREE):
     super().__init__(dtstart, summary, work)
     rrule = vRecur()
     rrule['FREQ'] = vFrequency('YEARLY')
     self.add('rrule', rrule)
Beispiel #36
0
 def rrule(self):
     byday = dateutil.rrule.weekday(self.day_of_the_week)
     return icalendar.vRecur(freq='weekly', interval=self.skip_weeks + 1,
                             byday=byday)
def generate_recurrence_rule(interval, lastdate):
    until = lastdate + timedelta(hours=23, minutes=59, seconds=59)  # 最后一周结束
    return vRecur(freq="WEEKLY", until=until, interval=interval)
def seperate_lec(source, UID, cal):
    count = 1
    for course in source:
        if (course[1] == 'Dropped\n'):
            continue
        for x in range(6, len(course), 7):
            event = Event()
            if (course[x] != ' \n'):
                name = course[0].replace("\n", "")
                section = course[x + 1].replace("\n", "")
                component = course[x + 2].replace("\n", "")
            # Get date
            dates = course[x + 6].replace("\n", "").split(' ')
            if (dates[0] == 'TBA'):
                continue
            start_dates = dates[0].split('/')
            end_dates = dates[2].split('/')

            # Get time
            time = course[x + 3].replace("\n", "").split(' ')
            start_hour, start_minute = parseTime(time[1])
            end_hour, end_minute = parseTime(time[3])

            # Reccurance
            week = parseWeek(time[0])
            until = datetime(int(end_dates[2]), int(end_dates[1]),
                             int(end_dates[0]), end_hour, end_minute)
            rec = {
                'FREQ': 'WEEKLY',
                'INTERVAL': 1,
                'BYDAY': week,
                'UNTIL': until,
                'WKST': 'SU',
            }

            week_dic = {'MO': 0, 'TU': 1, 'WE': 2, 'TH': 3, 'FR': 4}

            # Prepare information
            summary = name + ' (' + component + ')'
            uid = UID + '_' + str(count)
            location = course[x + 4].replace("\n", "") + ', Waterloo, Canada'
            instructor = course[x + 5].replace("\n", "")
            description = (
                'Course name: %s %s (%s)\nLocation: %s\nInstructor: %s') % (
                    name, component, section, location, instructor)

            # Prepare Date
            dtstart = datetime(
                int(start_dates[2]),
                int(start_dates[1]),
                int(start_dates[0]),
                start_hour,
                start_minute,
            )
            dtend = datetime(int(start_dates[2]), int(start_dates[1]),
                             int(start_dates[0]), end_hour, end_minute)
            #             print(dtstart.weekday() - week_dic[week[0]])
            diff = week_dic[week[0]] - dtstart.weekday()

            dtstart += timedelta(days=diff)
            dtend += timedelta(days=diff)

            event['summary'] = vText(summary)
            event['uid'] = vText(uid)
            event['dtstamp'] = vDatetime(datetime.now())
            event['location'] = vText(location)
            event['description'] = vText(description)
            event['dtstart'] = vDatetime(dtstart)
            event['dtend'] = vDatetime(dtend)
            event['rrule'] = vRecur(rec)

            cal.add_component(event)
            count += 1
Beispiel #39
0
 def to_ical(self):
     rrule = icalendar.vRecur(
         dict((k, v) for k, v in self.to_dict(True).items()
              if not (type(v) == str and v == ''
                      or type(v) == list and len(v) == 0)))
     return rrule
        delta += 1
        startWeekday += 1
        if (startWeekday > 6):
            startWeekday = 0

    startdate += timedelta(days=delta)

    # Make .ics file
    cal = Calendar()
    cal.add('prodid', 'I School Course Calendar')
    cal.add('version', '2.0')
    event = Event()
    event.add('summary', coursetitle)
    event.add('location', course.location)
    event.add(
        'dtstart',
        datetime(year, startdate.month, startdate.day, starthour, startminute,
                 0))
    event.add(
        'dtend',
        datetime(year, startdate.month, startdate.day, endhour, endminute, 0))
    event.add('tzid', 'California-Los_Angeles')
    finishedt = datetime(year, endmonth, endday, 0, 0, 0)
    event.add('rrule', vRecur(freq='weekly', byday=coursedays,
                              until=finishedt))
    cal.add_component(event)
    f = open(coursetitle + '.ics', 'wb')
    f.write(cal.as_string())
    print 'Wrote: ' + coursetitle + '.ics'
    f.close()
Beispiel #41
0
    def map_event(self, e):
        """Convert a palmFile event into an icalendar.Event."""

        event = icalendar.Event()
        event.add('dtstart', self.mkdate(e['startTime'], e['untimed']))
        event.add('dtend', self.mkdate(e['endTime'], e['untimed']))
        event.add('summary', self.clean(e['text']))
        if e['note']:
            event.add('description', self.clean(e['note']))
        if e['category']:
            event.add('categories', self.categories[e['category']])

        repeat = e['repeatEvent']

        if repeat['repeatEventFlag'] == 0:
            # No recurrence
            return event

        if repeat.get('dateExceptions'):
            event['exdate'] = icalendar.prop.vDDDLists([self.mkdate(exc, e['untimed']) for exc in repeat['dateExceptions']])

        recur = icalendar.vRecur()

        recur['until'] = self.mkdate(repeat['endDate'], e['untimed'])
        if repeat['interval'] != 1:
            recur['interval'] = repeat['interval']

        if repeat['brand'] == 1:
            # Daily
            recur['freq'] = 'daily'
            # Repeat every sth day of the week
            recur['byday'] = [self.DAY_NAMES[repeat['brandDayIndex']]]
        elif repeat['brand'] == 2:
            # weekly
            recur['freq'] = 'weekly'
            # Mask of week days to use
            # 1 => Sunday, 2 => Monday, 4 => Tuesday, 64 => Saturday
            days_mask = ord(repeat['brandDaysMask'])
            for day_mask, day in self.DAYMASK_TRANSLATION.items():
                days = []
                if days_mask & day_mask:
                    days.append(day)
                if days:
                    recur['byday'] = days

        elif repeat['brand'] == 3:
            # monthly, by day
            recur['freq'] = 'monthly'
            # Day of the week
            recur['byday'] = [self.DAY_NAMES[repeat['brandDayIndex']]]
            # Week of the month
            if repeat['brandWeekIndex'] == 4:
                # Last week of the month
                recur['bysetpos'] = -1
            else:
                recur['bysetpos'] = repeat['brandWeekIndex']
        elif repeat['brand'] == 4:
            # monthly, by date
            recur['freq'] = 'monthly'
            # Day in the month
            recur['bymonthday'] = repeat['brandDayNumber']

        elif repeat['brand'] == 5:
            # yearly, by date
            recur['freq'] = 'yearly'
            # Day in the month
            recur['bymonthday'] = repeat['brandDayNumber']
            # Month in the year
            recur['bymonth'] = repeat['brandMonthIndex'] + 1

        elif repeat['brand'] == 6:
            # yearly, by day
            recur['freq'] = 'yearly'

        event['rrule'] = recur

        return event
Beispiel #42
0
def create_ics(courses, filename):
    cal = Calendar()
    for c in courses:
        course = courses[c]

        # create a new calender event for each lecture time (for classes like ENGR 120)
        for schedule in course["schedule"]:
            event = Event()

            # Time formatting is similar to unix "date" command
            start_time = datetime.strptime(
                f'{schedule["start_date"]} {schedule["start_time"]}',
                '%b %d, %Y %I:%M %p')
            end_time = datetime.strptime(
                f'{schedule["start_date"]} {schedule["end_time"]  }',
                '%b %d, %Y %I:%M %p')
            end_date = datetime.strptime(
                f'{schedule["end_date"]  } {schedule["end_time"]  }',
                '%b %d, %Y %I:%M %p')
            days = schedule["days"]

            numeric_days = []
            for d in days:
                numeric_days.append(ics_day_to_number(d))

            # fix if the start date is not an included day
            while start_time.weekday() not in numeric_days:
                try:
                    start_time = start_time.replace(day=start_time.day + 1)
                except ValueError:
                    if start_time.month == 12:
                        start_time = start_time.replace(day=1,
                                                        month=1,
                                                        year=start_time.year +
                                                        1)
                    else:
                        start_time = start_time.replace(
                            day=1, month=start_time.month + 1)
            else:
                # update end time accordingly
                end_time = datetime.combine(date=start_time.date(),
                                            time=end_time.time())

            event.add("summary", f"{course['code']} {course['section']}")

            event.add("dtstart", start_time)
            event.add("dtend", end_time)
            event.add("dtstamp", datetime.now())

            event.add("location", schedule["location"])

            event.add(
                'rrule',
                vRecur({
                    "freq": "WEEKLY",
                    "interval": 1,
                    "until": end_date,
                    "byday": days
                }))

            cal.add_component(event)

    with open(f"{filename}.ics", "wb") as f:
        f.write(cal.to_ical())
        f.close()
        start_date = datetime.datetime.strptime((date["start_date"]), "%Y-%m-%d")+d
        end_date = datetime.datetime.strptime((date["end_date"]), "%Y-%m-%d")+d
        
        start_hour = datetime.timedelta(hours=ev['start_time'])
        duration = datetime.timedelta(hours=int(ev['duration']))

        start_date_time = (start_date+start_hour)
        end_date_time = (start_date_time+duration)

        event = Event()
        event.add('summary', ev['title'])
        event.add('location', ev['location'])
    
        
        recur = vRecur(FREQ='weekly', UNTIL=end_date)
        event.add('rrule', recur)
    
        event.add('dtstart',start_date_time)
        # Add an extra day as RFC2445 appears to suggest that is the correct way,
        # and that's the way Google Calendar treats it
        event.add('dtend', end_date_time)
        event.add('class', 'PUBLIC')
    
        cal.add_component(event)

sys.stdout.write(cal.to_ical())
# should validate at http://icalvalid.cloudapp.net/
import dateutil.parser
import datetime, time
import scraperwiki
Beispiel #44
0
def test_recur():
    event = Event.fromString(_get_text('event_dt_rr'), **EVENT_KWARGS)
    assert event.recurring is True
    assert event.recurpattern == 'FREQ=DAILY;COUNT=10'
    assert event.recurobject == vRecur({'COUNT': [10], 'FREQ': ['DAILY']})
Beispiel #45
0
def ical_feed(request, cal_id):
    """
    iCal feed
    Kept up-to-date
    Parameter: cal_id, which is a guid that is 1:1 with schedules in our database
    """
    cal = Calendar()
    cal.add('prodid', '-//Recal Course Planner//recal.io//')
    cal.add('version', '2.0')

    try:
        sched = Schedule.objects.get(Q(ical_uuid=uuid.UUID(cal_id)))
    except Schedule.DoesNotExist:
        return HttpResponseNotFound("Not Found")
    semester = sched.semester

    cal.add('X-WR-CALNAME',
            'ReCal %s (%s)' % (unicode(semester), sched.user.netid))
    cal.add('X-WR-CALDESC', sched.title)  # 'ReCal Schedule'
    # https://msdn.microsoft.com/en-us/library/ee178699(v=exchg.80).aspx. 15
    # minute updates.
    cal.add('X-PUBLISHED-TTL', 'PT15M')

    tz = pytz.timezone("US/Eastern")  # pytz.utc
    # recurrence
    ical_days = {0: 'MO', 1: 'TU', 2: 'WE', 3: 'TH', 4: 'FR'}
    builtin_days = {'M': 0, 'T': 1, 'W': 2, 'Th': 3, 'F': 4}

    #data = [hydrate_course_dict(Course.objects.get(Q(id=course['course_id']))) for course in json.loads(sched.enrollments)]

    # 0-6, monday is 0, sunday is 6. we will have values of 0 (Monday) or 2
    # (Wednesday)
    day_of_week_semester_start = semester.start_date.weekday()

    for course_obj in json.loads(sched.enrollments):
        # course = Course.objects.get(Q(id=course_obj['course_id'])) #
        # course_obj is json object; course is model
        for section_id in course_obj['sections']:
            section = Section.objects.get(Q(pk=section_id))
            for meeting in section.meetings.all():
                event = Event()
                event.add('summary', unicode(section))  # name of the event
                event.add('location',
                          vText(meeting.location + ', Princeton, NJ'))

                # compute first meeting date.
                # days when the class meets. convert them to day difference
                # relative to first date of the semester
                # split by space. format: 0-4. monday is 0, friday is 4.
                # matches python weekday() format.
                daysofweek = [builtin_days[i] for i in meeting.days.split()]
                if len(daysofweek) == 0:
                    # no meetings -- skip
                    continue
                dayofweek_relative_to_semester_start = []
                for dow in daysofweek:
                    diff = dow - day_of_week_semester_start
                    if diff < 0:
                        diff += 7  # add a week
                    dayofweek_relative_to_semester_start.append(diff)
                # all must be positive
                assert all(
                    [d >= 0 for d in dayofweek_relative_to_semester_start])
                # a T,Th class will have first meeting on T if semester starts
                # on M, or on Th if semester starts on Wed.
                first_meeting_dayofweek = min(
                    dayofweek_relative_to_semester_start)

                # get meeting time
                # meeting.start_time, meeting.end_time examples: "03:20 PM",
                # "10:00 AM"
                start_time = dt_parser.parse(meeting.start_time)
                end_time = dt_parser.parse(meeting.end_time)

                # add event time.
                event.add(
                    'dtstart',
                    tz.localize(
                        datetime(semester.start_date.year, semester.start_date.
                                 month, semester.start_date.day,
                                 start_time.hour, start_time.minute, 0) +
                        timedelta(days=first_meeting_dayofweek))
                )  # year,month,day, hour,min,second in ET
                event.add(
                    'dtend',
                    tz.localize(
                        datetime(semester.start_date.year, semester.start_date.
                                 month, semester.start_date.day, end_time.hour,
                                 end_time.minute, 0) +
                        timedelta(days=first_meeting_dayofweek)))
                # "property specifies the DATE-TIME that iCalendar object was created". per 3.8.7.2 of RFC 5545, must be in UTC
                event.add(
                    'dtstamp',
                    tz.localize(
                        datetime(semester.start_date.year,
                                 semester.start_date.month,
                                 semester.start_date.day, 0, 0, 0)))

                # recurring event config
                # producing e.g.: RRULE:FREQ=WEEKLY;UNTIL=[LAST DAY OF SEMESTER
                # + 1];WKST=SU;BYDAY=TU,TH
                selected_days = [ical_days[i] for i in sorted(daysofweek)
                                 ]  # formatted for ical
                end_date = tz.localize(
                    datetime(semester.end_date.year, semester.end_date.month,
                             semester.end_date.day, 0, 0, 0) +
                    timedelta(days=1))  # [LAST DAY OF SEMESTER + 1]
                event.add(
                    'rrule',
                    vRecur({
                        'FREQ': 'WEEKLY',
                        'UNTIL': end_date,
                        'WKST': 'SU',
                        'BYDAY': selected_days
                    }))
                cal.add_component(event)

    ical = cal.to_ical()

    # filter out blank lines
    #filtered = filter(lambda x: not re.match(r'^\s*$', x), ical)
    # print filtered
    return HttpResponse(ical, 'text/calendar', status=200)
Beispiel #46
0
 def recurobject(self):
     if 'RRULE' in self._vevents[self.ref]:
         return self._vevents[self.ref]['RRULE']
     else:
         return icalendar.vRecur()
Beispiel #47
0
def test_recur():
    event = Event.fromString(_get_text('event_dt_rr'), **EVENT_KWARGS)
    assert event.recurring is True
    assert event.recurpattern == 'FREQ=DAILY;COUNT=10'
    assert event.recurobject == vRecur({'COUNT': [10], 'FREQ': ['DAILY']})
Beispiel #48
-1
def contacts_ics():
    cal = Calendar()
    cal.add('prodid', vText('-//choochootrain//Auto-generated//EN'))
    cal.add('version', vText('2.0'))
    cal.add('calscale', vText('gregorian'))
    cal.add('method', vText('publish'))

    cal.add('x-wr-calname', vText('Birthdays'))
    cal.add('x-wr-timezone', vText('America/Los_Angeles'))
    cal.add('x-wr-caldesc', vText('Autogenerated calendar of birthday events'))

    conn = sqlite3.connect("data/contacts.db")
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM contacts order by birthyear, birthmonth, birthday")

    for id, name, day, month, year in cursor.fetchall():
        event = Event()
        event.add('summary', "%s's birthday" % name)

        start = datetime.datetime(day=day, month=month, year=year if year is not None else 2014)
        event.add('dtstart', vDDDTypes(start))
        event.add('dtend', vDDDTypes(start + datetime.timedelta(days=1)))
        event.add('rrule', vRecur(freq='yearly'))
        cal.add_component(event)

    return Response(cal.to_ical(), mimetype="text/calendar")