Module: Protocol::Caldav::Ical::Expand
- Defined in:
- lib/protocol/caldav/ical/expand.rb
Class Method Summary collapse
-
.expand(component, range_start:, range_end:, max_occurrences: 10000) ⇒ Object
Expand a recurring VCALENDAR into individual instances.
Class Method Details
.expand(component, range_start:, range_end:, max_occurrences: 10000) ⇒ Object
Expand a recurring VCALENDAR into individual instances. Returns a serialized VCALENDAR string with RRULE removed and each occurrence as a separate VEVENT with RECURRENCE-ID.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/protocol/caldav/ical/expand.rb', line 14 def (component, range_start:, range_end:, max_occurrences: 10000) if component.name.casecmp?('VCALENDAR') base = component.find_components('VEVENT').find { |v| v.find_property('RRULE') } if base uid = base.find_property('UID')&.value overrides = {} component.find_components('VEVENT').each do |v| rid = v.find_property('RECURRENCE-ID') if rid && v.find_property('UID')&.value == uid rid_time = Filter::Match.send(:parse_datetime_string, rid.value.strip) if rid_time overrides[rid_time] = v end end end dtstart_prop = base.find_property('DTSTART') dtstart = Filter::Match.send(:parse_datetime_string, dtstart_prop.value.strip) if dtstart dtend = Filter::Match.send(:parse_ical_datetime, base, 'DTEND') if dtend duration = (dtend - dtstart).to_i else duration = 3600 end rrule = base.find_property('RRULE').value.strip exdates = base.find_all_properties('EXDATE').filter_map do |ex| Filter::Match.send(:parse_datetime_string, ex.value.strip) end occurrences = Rrule.( dtstart: dtstart, rrule_value: rrule, range_start: range_start, range_end: range_end, exdates: exdates, max_count: max_occurrences, ) instances = occurrences.map do |occ_start| override = overrides[occ_start] if override serialize_vevent_instance(override, occ_start) else (base, occ_start, duration) end end overrides.each do |rid_time, override_vevent| if occurrences.any? { |o| Rrule.send(:times_equal?, o, rid_time) } next end odt = Filter::Match.send(:parse_ical_datetime, override_vevent, 'DTSTART') unless odt && odt >= range_start && odt < range_end next end instances << serialize_vevent_instance(override_vevent, rid_time) end "BEGIN:VCALENDAR\r\n#{instances.join}END:VCALENDAR\r\n" else serialize_component(component) end else serialize_component(component) end else serialize_component(component) end end |