fix: allows until to be defined as datetime with timezone. Shamelessly copied code from @mbafford: https://github.com/jazzband/icalevents/pull/109/files

pull/97/head
Martin Eigenmann 2022-12-18 12:00:51 +01:00
rodzic 266ca3d24d
commit 00f3392230
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 069D1EE3806CA368
3 zmienionych plików z 87 dodań i 3 usunięć

Wyświetl plik

@ -340,7 +340,9 @@ def parse_events(
# 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"])
@ -487,13 +489,29 @@ def parse_rrule(component):
def conform_until(until, dtstart):
if type(dtstart) is datetime:
return (
# If we have timezone defined adjust for daylight saving time
if type(until) is datetime:
until_offset = (
until.astimezone(dtstart.tzinfo).utcoffset()
if until.tzinfo is not None and dtstart.tzinfo is not None
else None
)
if until_offset is not None:
return until + abs(until_offset)
offset = dtstart.tzinfo.utcoffset(dtstart) if dtstart.tzinfo else None
normalized_until = (
until.astimezone(UTC)
if type(until) is datetime
else datetime(
year=until.year, month=until.month, day=until.day, tzinfo=UTC
)
) + dtstart.tzinfo.utcoffset(dtstart)
)
if offset:
return normalized_until + offset
return normalized_until
elif type(dtstart) is date:
return (
until.date() + timedelta(days=1) if type(until) is datetime else until

Wyświetl plik

@ -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

Wyświetl plik

@ -776,3 +776,22 @@ class ICalEventsTests(unittest.TestCase):
)
self.assertEqual(len(events), len(times))
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