Standard/Daylight parsing is very slow if start is far in the past
justinhoward opened this issue · comments
I'm parsing a calendar from Office 365 with the following:
BEGIN:VCALENDAR
METHOD:PUBLISH
PRODID:Microsoft Exchange Server 2010
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Pacific Standard Time
BEGIN:STANDARD
DTSTART:16010101T020000
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:16010101T020000
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3
END:DAYLIGHT
END:VTIMEZONE
The DTSTART
properties are set very far in the past. This causes IceCube::Schedule.previous_occurrence
to take a very long time (several seconds per event).
icalendar/lib/icalendar/timezone.rb
Line 86 in 5214946
For a calendar with many events, parsing a whole calendar can take minutes.
One solution I've considered is to cache the enumerated occurrences. Another solution might be to look at RRULE
and manually adjust the start date to be a single occurrence in the past (for example subtract 1 year from local).
Of the two solutions, I think I prefer the latter, because it should require less computation time. I experimented with that solution and it seems to work well and also reduces the parse time of my test from about 30s to 200ms.
I'm happy to submit a PR if that sounds like a good solution.
I just realized that it gets more complicated if there are multiple RRULE
values or if there are RDATE
values. It might be better to go with the cache approach. Caching could be tricky since we're working with an infinite series, but we could cache a "window" of time and only increase it if necessary. It needs more thought.
Of course, another solution in my case is to just modify dtstart
before parsing, but if it can be fixed upstream, I'd prefer that.
Closing this in favor of #214.