Skip to content

Commit

Permalink
Added support for parsing VEVENT from iCal format
Browse files Browse the repository at this point in the history
  • Loading branch information
iainbeeston committed Jan 13, 2019
1 parent 49534bf commit a5a11d7
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Current

* [FEATURE] Added support for parsing VEVENT from iCal format (#465)

## 0.16.3 / 2018-07-23

* [FEATURE] Added support for parsing RDATE from iCal format
Expand Down
51 changes: 40 additions & 11 deletions lib/ice_cube/parsers/ical_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,57 @@ module IceCube
class IcalParser
def self.schedule_from_ical(ical_string, options = {})
data = {}
parser = :parse_line
ical_string.each_line do |line|
(property, value) = line.split(':')
(property, tzid) = property.split(';')

parser, property, value = *send(parser, property, value)

case property
when :start_time,
:end_time
data[property] = value
when :rtimes,
:rrules,
:extimes
data[property] ||= []
data[property] += value
end
end
Schedule.from_hash data
end

def self.parse_line(property, value)
result = case property
when 'DTSTART'
data[:start_time] = TimeUtil.deserialize_time(value)
[:parse_line, :start_time, TimeUtil.deserialize_time(value)]
when 'DTEND'
data[:end_time] = TimeUtil.deserialize_time(value)
[:parse_line, :end_time, TimeUtil.deserialize_time(value)]
when 'RDATE'
data[:rtimes] ||= []
data[:rtimes] += value.split(',').map { |v| TimeUtil.deserialize_time(v) }
[:parse_line, :rtimes, value.split(',').map { |v| TimeUtil.deserialize_time(v) }]
when 'EXDATE'
data[:extimes] ||= []
data[:extimes] += value.split(',').map { |v| TimeUtil.deserialize_time(v) }
[:parse_line, :extimes, value.split(',').map { |v| TimeUtil.deserialize_time(v) }]
when 'DURATION'
data[:duration] # FIXME
nil # FIXME
when 'RRULE'
data[:rrules] ||= []
data[:rrules] += [rule_from_ical(value)]
[:parse_line, :rrules, [rule_from_ical(value)]]
when 'BEGIN'
[:parse_vevent_line] if value.chomp == 'VEVENT'
end
end
Schedule.from_hash data

result || [:parse_line]
end

def self.parse_vevent_line(property, value)
result = case property
when 'DTSTART'
[:parse_vevent_line, :rtimes, [TimeUtil.deserialize_time(value)]]
when 'END'
[:parse_line] if value.chomp == 'VEVENT'
end

result || [:parse_vevent_line]
end

def self.rule_from_ical(ical)
Expand Down
18 changes: 18 additions & 0 deletions spec/examples/from_ical_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ module IceCube
RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU;BYDAY=FR
ICAL

ical_string_with_events = <<-ICAL.gsub(/^\s*/, '' )
BEGIN:VEVENT
DTSTART;VALUE=DATE:20120406
DTEND;VALUE=DATE:20120407
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20120409
DTEND;VALUE=DATE:20120410
END:VEVENT
ICAL

def sorted_ical(ical)
ical.split(/\n/).sort.map { |field|
k, v = field.split(':')
Expand Down Expand Up @@ -390,6 +401,13 @@ def sorted_ical(ical)
end
end

describe 'events' do
it "converts each event into it's own recurrence time" do
schedule = IceCube::Schedule.from_ical ical_string_with_events
expect(schedule.recurrence_times.count).to eq(2)
end
end

describe 'invalid ical data' do
shared_examples_for('an invalid ical string') do
it do
Expand Down

0 comments on commit a5a11d7

Please sign in to comment.