Skip to content

Commit a5a11d7

Browse files
committed
Added support for parsing VEVENT from iCal format
1 parent 49534bf commit a5a11d7

File tree

3 files changed

+62
-11
lines changed

3 files changed

+62
-11
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Current
4+
5+
* [FEATURE] Added support for parsing VEVENT from iCal format (#465)
6+
37
## 0.16.3 / 2018-07-23
48

59
* [FEATURE] Added support for parsing RDATE from iCal format

lib/ice_cube/parsers/ical_parser.rb

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,57 @@ module IceCube
22
class IcalParser
33
def self.schedule_from_ical(ical_string, options = {})
44
data = {}
5+
parser = :parse_line
56
ical_string.each_line do |line|
67
(property, value) = line.split(':')
78
(property, tzid) = property.split(';')
9+
10+
parser, property, value = *send(parser, property, value)
11+
812
case property
13+
when :start_time,
14+
:end_time
15+
data[property] = value
16+
when :rtimes,
17+
:rrules,
18+
:extimes
19+
data[property] ||= []
20+
data[property] += value
21+
end
22+
end
23+
Schedule.from_hash data
24+
end
25+
26+
def self.parse_line(property, value)
27+
result = case property
928
when 'DTSTART'
10-
data[:start_time] = TimeUtil.deserialize_time(value)
29+
[:parse_line, :start_time, TimeUtil.deserialize_time(value)]
1130
when 'DTEND'
12-
data[:end_time] = TimeUtil.deserialize_time(value)
31+
[:parse_line, :end_time, TimeUtil.deserialize_time(value)]
1332
when 'RDATE'
14-
data[:rtimes] ||= []
15-
data[:rtimes] += value.split(',').map { |v| TimeUtil.deserialize_time(v) }
33+
[:parse_line, :rtimes, value.split(',').map { |v| TimeUtil.deserialize_time(v) }]
1634
when 'EXDATE'
17-
data[:extimes] ||= []
18-
data[:extimes] += value.split(',').map { |v| TimeUtil.deserialize_time(v) }
35+
[:parse_line, :extimes, value.split(',').map { |v| TimeUtil.deserialize_time(v) }]
1936
when 'DURATION'
20-
data[:duration] # FIXME
37+
nil # FIXME
2138
when 'RRULE'
22-
data[:rrules] ||= []
23-
data[:rrules] += [rule_from_ical(value)]
39+
[:parse_line, :rrules, [rule_from_ical(value)]]
40+
when 'BEGIN'
41+
[:parse_vevent_line] if value.chomp == 'VEVENT'
2442
end
25-
end
26-
Schedule.from_hash data
43+
44+
result || [:parse_line]
45+
end
46+
47+
def self.parse_vevent_line(property, value)
48+
result = case property
49+
when 'DTSTART'
50+
[:parse_vevent_line, :rtimes, [TimeUtil.deserialize_time(value)]]
51+
when 'END'
52+
[:parse_line] if value.chomp == 'VEVENT'
53+
end
54+
55+
result || [:parse_vevent_line]
2756
end
2857

2958
def self.rule_from_ical(ical)

spec/examples/from_ical_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ module IceCube
119119
RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU;BYDAY=FR
120120
ICAL
121121

122+
ical_string_with_events = <<-ICAL.gsub(/^\s*/, '' )
123+
BEGIN:VEVENT
124+
DTSTART;VALUE=DATE:20120406
125+
DTEND;VALUE=DATE:20120407
126+
END:VEVENT
127+
BEGIN:VEVENT
128+
DTSTART;VALUE=DATE:20120409
129+
DTEND;VALUE=DATE:20120410
130+
END:VEVENT
131+
ICAL
132+
122133
def sorted_ical(ical)
123134
ical.split(/\n/).sort.map { |field|
124135
k, v = field.split(':')
@@ -390,6 +401,13 @@ def sorted_ical(ical)
390401
end
391402
end
392403

404+
describe 'events' do
405+
it "converts each event into it's own recurrence time" do
406+
schedule = IceCube::Schedule.from_ical ical_string_with_events
407+
expect(schedule.recurrence_times.count).to eq(2)
408+
end
409+
end
410+
393411
describe 'invalid ical data' do
394412
shared_examples_for('an invalid ical string') do
395413
it do

0 commit comments

Comments
 (0)