Handle non-UTC UNTIL datetime value when repeating ical events (#2241)
This commit is contained in:
parent
687fcc2829
commit
d38315def7
3 changed files with 63 additions and 0 deletions
|
|
@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Update notification text for "You're going on call" push notifications to include information about the shift start
|
||||
and end times by @joeyorlando ([#2131](https://github.com/grafana/oncall/pull/2131))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Handle non-UTC UNTIL datetime value when repeating ical events [#2241](https://github.com/grafana/oncall/pull/2241)
|
||||
|
||||
## v1.2.44 (2023-06-14)
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import datetime
|
||||
import re
|
||||
import typing
|
||||
from collections import defaultdict
|
||||
|
||||
|
|
@ -30,6 +31,8 @@ class AmixrUnfoldableCalendar(UnfoldableCalendar):
|
|||
"""
|
||||
|
||||
class RepeatedEvent(UnfoldableCalendar.RepeatedEvent):
|
||||
RE_DATETIME_VALUE = re.compile(r"\d+T\d+")
|
||||
|
||||
class Repetition(UnfoldableCalendar.RepeatedEvent.Repetition):
|
||||
"""
|
||||
A repetition of an event. Overridden version of
|
||||
|
|
@ -40,6 +43,26 @@ class AmixrUnfoldableCalendar(UnfoldableCalendar):
|
|||
|
||||
ATTRIBUTES_TO_DELETE_ON_COPY = ["RDATE", "EXDATE"]
|
||||
|
||||
def create_rule_with_start(self, rule_string, start):
|
||||
"""Override to handle issue with non-UTC UNTIL value including time information."""
|
||||
try:
|
||||
return super().create_rule_with_start(rule_string, start)
|
||||
except ValueError:
|
||||
# string: FREQ=WEEKLY;UNTIL=20191023T100000;BYDAY=TH;WKST=SU
|
||||
# ValueError: RRULE UNTIL values must be specified in UTC when DTSTART is timezone-aware
|
||||
# https://stackoverflow.com/a/49991809
|
||||
rule_list = rule_string.split(";UNTIL=")
|
||||
assert len(rule_list) == 2
|
||||
date_end_index = rule_list[1].find(";")
|
||||
if date_end_index == -1:
|
||||
date_end_index = len(rule_list[1])
|
||||
until_string = rule_list[1][:date_end_index]
|
||||
if self.RE_DATETIME_VALUE.match(until_string):
|
||||
rule_string = rule_list[0] + rule_list[1][date_end_index:] + ";UNTIL=" + until_string + "Z"
|
||||
return super().create_rule_with_start(rule_string, self.start)
|
||||
# otherwise, keep raising
|
||||
raise
|
||||
|
||||
def between(self, start, stop):
|
||||
"""Return events at a time between start (inclusive) and end (inclusive)"""
|
||||
span_start = self.to_datetime(start)
|
||||
|
|
|
|||
|
|
@ -1744,3 +1744,39 @@ def test_refresh_ical_final_schedule_all_day_date_event(
|
|||
calendar = icalendar.Calendar.from_ical(schedule.cached_ical_final_schedule)
|
||||
events = [component for component in calendar.walk() if component.name == ICAL_COMPONENT_VEVENT]
|
||||
assert len(events) == 0
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_event_until_non_utc(make_organization, make_schedule):
|
||||
organization = make_organization()
|
||||
cached_ical_primary_schedule = textwrap.dedent(
|
||||
"""
|
||||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:testing
|
||||
CALSCALE:GREGORIAN
|
||||
BEGIN:VEVENT
|
||||
CREATED:20220316T121102Z
|
||||
LAST-MODIFIED:20230127T151619Z
|
||||
DTSTAMP:20230127T151619Z
|
||||
UID:something
|
||||
SUMMARY:testing
|
||||
RRULE:FREQ=WEEKLY;UNTIL=20221231T010101
|
||||
DTSTART;TZID=Europe/Madrid:20220309T130000
|
||||
DTEND;TZID=Europe/Madrid:20220309T133000
|
||||
SEQUENCE:4
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
"""
|
||||
)
|
||||
|
||||
schedule = make_schedule(
|
||||
organization,
|
||||
schedule_class=OnCallScheduleICal,
|
||||
cached_ical_file_primary=cached_ical_primary_schedule,
|
||||
)
|
||||
|
||||
now = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
|
||||
# check this works without raising exception
|
||||
schedule.final_events("UTC", now, days=7)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue