diff --git a/icalevents/icalparser.py b/icalevents/icalparser.py index 2a3c206..586e3fb 100644 --- a/icalevents/icalparser.py +++ b/icalevents/icalparser.py @@ -362,10 +362,8 @@ def is_not_exception(date): # make rule.between happy and provide from, to points in time that have the same format as dtstart s = component["dtstart"].dt - if type(s) is date and not e.recurring: - f, t = date(start.year, start.month, start.day), date( - end.year, end.month, end.day - ) + if type(s) is date and e.recurring == False: + f, t = start, end elif type(s) is datetime and s.tzinfo: f, t = datetime( start.year, start.month, start.day, tzinfo=s.tzinfo @@ -537,7 +535,12 @@ def conform_until(until, dtstart): # Add exdates to the rruleset for exd in extract_exdates(component): if type(dtstart) is date: - rule.exdate(exd.replace(tzinfo=None)) + if type(exd) is date: + # Always convert exdates to datetimes because rrule.between does not like dates + # https://github.com/dateutil/dateutil/issues/938 + rule.exdate(datetime.combine(exd, datetime.min.time())) + else: + rule.exdate(exd.replace(tzinfo=None)) else: rule.exdate(exd) diff --git a/test/test_data/recurrence_tzinfo.ics b/test/test_data/recurrence_tzinfo.ics new file mode 100644 index 0000000..0d50879 --- /dev/null +++ b/test/test_data/recurrence_tzinfo.ics @@ -0,0 +1,29 @@ +BEGIN:VEVENT +DTSTAMP:20231221T180428Z +DTSTART;VALUE=DATE:20231127 +DTEND;VALUE=DATE:20231128 +SUMMARY:DSOC +CATEGORIES:other +SUBCALENDAR-ID:3dfdd9f8-dc5a-49b6-9b54-644138545076 +PARENT-CALENDAR-ID:f681d504-b5ed-4258-a68b-7deb867cf1bf +PARENT-CALENDAR-NAME: +SUBSCRIPTION-ID: +SUBCALENDAR-TZ-ID:America/Los_Angeles +SUBCALENDAR-NAME:My calendar +EVENT-ID:163463 +EVENT-ALLDAY:true +UID:20231012T192858Z--1042663660@my_org.com +DESCRIPTION: +ORGANIZER;X-CONFLUENCE-USER-KEY=09ceee004595a94a014595d847942220;CN=My Name;CUTYPE=INDIVIDUAL:mailto:my_email@email.com +RRULE:FREQ=WEEKLY;UNTIL=20240115;INTERVAL=1;BYDAY=MO +CREATED:20231012T192858Z +LAST-MODIFIED:20231130T174704Z +SEQUENCE:3 +X-CONFLUENCE-SUBCALENDAR-TYPE:other +TRANSP:TRANSPARENT +STATUS:CONFIRMED +EXDATE;VALUE=DATE:20231225 +EXDATE;VALUE=DATE:20231218 +EXDATE;VALUE=DATE:20231225 +EXDATE;VALUE=DATE:20231218 +END:VEVENT diff --git a/test/test_icalevents.py b/test/test_icalevents.py index 1573ff5..0f88de2 100644 --- a/test/test_icalevents.py +++ b/test/test_icalevents.py @@ -861,3 +861,21 @@ def test_google_2024(self): 5, "starts at 5 utc summer time (+2:00)", ) + + def test_regression_repeating_events_raise_an_error(self): + ical = "test/test_data/recurrence_tzinfo.ics" + start = date(2023, 1, 1) + end = date(2024, 12, 31) + + events = icalevents.events(file=ical, start=start, end=end, strict=True) + + self.assertEqual(len(events), 6, "6 events") + self.assertEqual(events[0].start, date(2023, 11, 27), "first on 27. nov") + self.assertEqual(events[1].start, date(2023, 12, 4), "second event on 4. dec") + self.assertEqual(events[2].start, date(2023, 12, 11), "third event on 11. dec") + self.assertEqual( + events[3].start, + date(2024, 1, 1), + "fourth event on 1. jan - 18. and 25. dec are excluded", + ) + self.assertEqual(events[4].start, date(2024, 1, 8), "fifth event on 8. jan")