Last active
August 20, 2023 06:11
-
-
Save jfeaver/6fb0eb391c86a86511d0a4c77b6a64f0 to your computer and use it in GitHub Desktop.
Parse full RRULEs to pass on to the rrule gem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# The rrule gem parses only the recurring rules of the RRULE specification. | |
# That is, the part that comes after "RRULE:" on the last line of an RRULE. To | |
# include the DTSTART, and EXDATE as options to the rrule gem, let's add our | |
# own interface. We remove the "RRULE:" and parse other rules and send them to | |
# the gem with the desired structure. | |
# | |
# Example RRULE which is now parseable as a string: | |
# | |
# EXDATE:19960402T010000Z,19960403T010000Z,19960404T010000Z | |
# DTSTART:19960401T000000Z | |
# RRULE:FREQ=WEEKLY;BYHOUR=2;BYMINUTE=0;BYDAY=WE | |
# | |
# See the RRULE specification: | |
# https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html | |
module RRule::Parse | |
refine RRule.singleton_class do | |
def parse(rrule, **options) | |
lines = rrule.split("\n") | |
dt_start = nil | |
tz_id = nil | |
ex_date = nil | |
rule = nil | |
lines.each do |line| | |
case | |
when line.match?(/^DTSTART/) | |
dt_start = Time.new(line.match(/:(.*)$/)[1]).utc | |
tz_id_match = line.match(/TZID=(.*):/) | |
tz_id = tz_id_match[1] if tz_id_match | |
when line.match?(/^EXDATE/) | |
ex_date = line.match(/:(.*)$/)[1].split(',').map { |time| Time.new(time).utc } | |
when line.match?(/^RRULE/) | |
rule = line.sub(/^RRULE*:/, '') | |
when line.include?('FREQ') | |
rule = line | |
end | |
end | |
raise RRule::InvalidRRule unless rule | |
parsed_options = { | |
dtstart: dt_start, | |
tzid: tz_id, | |
exdate: ex_date | |
}.compact | |
RRule::Rule.new(rule, **parsed_options.merge(options)) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment