Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle multiple recurrence exclude entries on the same EXDATE line #109

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 6 additions & 3 deletions icalevents/icalparser.py
Expand Up @@ -344,9 +344,10 @@ def parse_events(content, start=None, end=None, default_span=timedelta(days=7)):
found = []
recurrence_ids = []

# Skip dates that are stored as exceptions.
exceptions = {}
for component in calendar.walk():
# Skip dates that are stored as exceptions.
exceptions = {}

if component.name == "VEVENT":
e = create_event(component, cal_tz)

Expand All @@ -359,7 +360,9 @@ def parse_events(content, start=None, end=None, default_span=timedelta(days=7)):
# Deal with the fact that sometimes it's a list and
# sometimes it's a singleton
exlist = []
if isinstance(component["EXDATE"], list):
if isinstance(component["EXDATE"], vDDDLists):
exlist = component["EXDATE"].dts
elif isinstance(component["EXDATE"], list):
exlist = component["EXDATE"]
else:
exlist.append(component["EXDATE"])
Expand Down
47 changes: 47 additions & 0 deletions test/test_data/multi_exdate_same_line_ms.ics
@@ -0,0 +1,47 @@
BEGIN:VCALENDAR
METHOD:PUBLISH
PRODID:Microsoft Exchange Server 2010
VERSION:2.0
X-WR-CALNAME:Calendar
BEGIN:VTIMEZONE
TZID:Eastern Standard Time
BEGIN:STANDARD
DTSTART:16010101T020000
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:16010101T020000
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
DESCRIPTION:Test event that has an RRULE with multiple EXDATE
RRULE:FREQ=WEEKLY;UNTIL=20220429T150000Z;INTERVAL=1;BYDAY=FR;WKST=MO
EXDATE;TZID=Eastern Standard Time:20220318T110000,20220401T110000,20220408T
110000
UID:040000008200R00074P5O7101N82R00800000000R0Q793689428Q801000000000000000
010000000QOPN4SS024R0264S9P0Q7OOQQ16PN399
SUMMARY:Recurring With Exclusions
DTSTART;TZID=Eastern Standard Time:20220311T110000
DTEND;TZID=Eastern Standard Time:20220311T113000
CLASS:PUBLIC
PRIORITY:5
DTSTAMP:20220330T125447Z
TRANSP:OPAQUE
STATUS:CONFIRMED
SEQUENCE:0
LOCATION:Microsoft Teams Meeting
X-MICROSOFT-CDO-APPT-SEQUENCE:0
X-MICROSOFT-CDO-BUSYSTATUS:BUSY
X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
X-MICROSOFT-CDO-IMPORTANCE:1
X-MICROSOFT-CDO-INSTTYPE:1
X-MICROSOFT-DONOTFORWARDMEETING:FALSE
X-MICROSOFT-DISALLOW-COUNTER:FALSE
END:VEVENT
END:VCALENDAR
21 changes: 20 additions & 1 deletion test/test_icalevents.py
Expand Up @@ -425,7 +425,7 @@ def test_cest(self):

evs = icalevents.events(file=ical, start=start, end=end)

self.assertEqual(len(evs), 115, "4 events in total")
self.assertEqual(len(evs), 116, "4 events in total")

def test_transparent(self):
ical = "test/test_data/transparent.ics"
Expand All @@ -450,3 +450,22 @@ def test_status_and_url(self):
self.assertEqual(ev3.status, "CANCELLED")
self.assertEqual(ev4.status, "CANCELLED")
self.assertEqual(ev5.status, None)

def test_multi_exdate_same_line(self):
ical = "test/test_data/multi_exdate_same_line_ms.ics"
tz = gettz("America/New_York")
start = date(2022, 3, 1)
end = date(2022, 5, 1)

evs = icalevents.events(file=ical, start=start, end=end)

# parsing starts at 2022-03-01
self.assertEqual(evs[0].start, datetime(2022, 3, 11, 11, 0, 0, tzinfo=tz))
# 2022-03-18 is excluded by EXDATE rule
self.assertEqual(evs[1].start, datetime(2022, 3, 25, 11, 0, 0, tzinfo=tz))
# 2022-04-01 is excluded by EXDATE rule
# 2022-04-08 is excluded by EXDATE rule
self.assertEqual(evs[2].start, datetime(2022, 4, 15, 11, 0, 0, tzinfo=tz))
self.assertEqual(evs[3].start, datetime(2022, 4, 22, 11, 0, 0, tzinfo=tz))
self.assertEqual(evs[4].start, datetime(2022, 4, 29, 11, 0, 0, tzinfo=tz))
# parsing stops at 2022-05-01