1 2 3 4 5 6 7 8 9 10 11 12 13 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 79 80 81 82 83 84 85 86
|
module IceCube
class IcalParser
def self.schedule_from_ical(ical_string, options = {})
data = {}
ical_string.each_line do |line|
(property, value) = line.split(':')
(property, _tzid) = property.split(';')
case property
when 'DTSTART'
data[:start_time] = TimeUtil.deserialize_time(value)
when 'DTEND'
data[:end_time] = TimeUtil.deserialize_time(value)
when 'RDATE'
data[:rtimes] ||= []
data[:rtimes] += value.split(',').map { |v| TimeUtil.deserialize_time(v) }
when 'EXDATE'
data[:extimes] ||= []
data[:extimes] += value.split(',').map { |v| TimeUtil.deserialize_time(v) }
when 'DURATION'
data[:duration] # FIXME
when 'RRULE'
data[:rrules] ||= []
data[:rrules] += [rule_from_ical(value)]
end
end
Schedule.from_hash data
end
def self.rule_from_ical(ical)
raise ArgumentError, 'empty ical rule' if ical.nil?
validations = {}
params = {validations: validations, interval: 1}
ical.split(';').each do |rule|
(name, value) = rule.split('=')
raise ArgumentError, "Invalid iCal rule component" if value.nil?
value.strip!
case name
when 'FREQ'
params[:rule_type] = "IceCube::#{value[0]}#{value.downcase[1..-1]}Rule"
when 'INTERVAL'
params[:interval] = value.to_i
when 'COUNT'
params[:count] = value.to_i
when 'UNTIL'
params[:until] = TimeUtil.deserialize_time(value).utc
when 'WKST'
params[:week_start] = TimeUtil.ical_day_to_symbol(value)
when 'BYSECOND'
validations[:second_of_minute] = value.split(',').map(&:to_i)
when 'BYMINUTE'
validations[:minute_of_hour] = value.split(',').map(&:to_i)
when 'BYHOUR'
validations[:hour_of_day] = value.split(',').map(&:to_i)
when 'BYDAY'
dows = {}
days = []
value.split(',').each do |expr|
day = TimeUtil.ical_day_to_symbol(expr.strip[-2..-1])
if expr.strip.length > 2 # day with occurence
occ = expr[0..-3].to_i
dows[day].nil? ? dows[day] = [occ] : dows[day].push(occ)
days.delete(TimeUtil.sym_to_wday(day))
else
days.push TimeUtil.sym_to_wday(day) if dows[day].nil?
end
end
validations[:day_of_week] = dows unless dows.empty?
validations[:day] = days unless days.empty?
when 'BYMONTHDAY'
validations[:day_of_month] = value.split(',').map(&:to_i)
when 'BYMONTH'
validations[:month_of_year] = value.split(',').map(&:to_i)
when 'BYYEARDAY'
validations[:day_of_year] = value.split(',').map(&:to_i)
when 'BYSETPOS'
else
validations[name] = nil # invalid type
end
end
Rule.from_hash(params)
end
end
end
|