Convert RRULE UNTIL with no tzinfo to UTC

Since DTSTART is always given tzinfo, any UNTIL in an RRULE
must be tz-aware and in UTC.

See: irgangla/icalevents#47
pull/49/head
Tom Daff 2019-04-02 10:26:46 +01:00
rodzic acec3dd71c
commit 062fb93951
3 zmienionych plików z 40 dodań i 0 usunięć

Wyświetl plik

@ -259,6 +259,15 @@ def parse_rrule(component, tz=UTC):
rrules = component['rrule']
if not isinstance(rrules, list):
rrules = [rrules]
# Since DTSTART are always made timezone aware, UNTIL with no tzinfo
# must be converted to UTC.
for rule in rrules:
until = rule.get("until")
for idx, dt in enumerate(until or []):
if not hasattr(dt, 'tzinfo'):
until[idx] = normalize(normalize(dt, tz=tz), tz=UTC)
# Parse the rrules, might return a rruleset instance, instead of rrule
rule = rrulestr('\n'.join(x.to_ical().decode() for x in rrules), dtstart=normalize(component['dtstart'].dt, tz=tz))

Wyświetl plik

@ -0,0 +1,19 @@
BEGIN:VCALENDAR
BEGIN:VTIMEZONE
TZID:Europe/Berlin
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;VALUE=DATE:20151030
DTEND;VALUE=DATE:20151031
DESCRIPTION:All-day event recurring on tuesday each week
SUMMARY:Recurring All-day Event
RRULE:FREQ=WEEKLY;BYDAY=TU;UNTIL=20341031
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=Europe/London:20180522T120000
DTEND;TZID=Europe/London:20180522T130000
DESCRIPTION:Daily lunchtime event with specified hours
SUMMARY:Daily lunch event
RRULE:FREQ=DAILY;UNTIL=20330523T060000Z
END:VEVENT
END:VCALENDAR

Wyświetl plik

@ -107,6 +107,18 @@ class ICalEventsTests(unittest.TestCase):
self.assertEqual(ev_2.description, "All-day event recurring on tuesday each week")
self.assertTrue(ev_2.all_day, "Recurring All-day Event's second instance is an all-day event")
def test_events_rrule_until(self):
ical = "test/test_data/rrule_until.ics"
start = date(2019, 4, 2)
end = date(2019, 4, 3)
evs = icalevents.events(file=ical, start=start, end=end)
self.assertEqual(len(evs), 2)
self.assertEqual(evs[0].recurring, True)
self.assertEqual(evs[0].summary, "Recurring All-day Event")
self.assertEqual(evs[1].recurring, True)
self.assertEqual(evs[1].summary, "Daily lunch event")
def test_event_attributes(self):
ical = "test/test_data/basic.ics"