Skip to content

Commit 8db090e

Browse files
committed
Parse time zones when creating schedules from ICAL; fix DST test bug #295
1 parent b003063 commit 8db090e

File tree

3 files changed

+44
-13
lines changed

3 files changed

+44
-13
lines changed

lib/ice_cube/parsers/ical_parser.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ def self.schedule_from_ical(ical_string, options = {})
77
(property, tzid) = property.split(';')
88
case property
99
when 'DTSTART'
10-
data[:start_time] = Time.parse(value)
10+
data[:start_time] = _parse_in_tzid(value, tzid)
1111
when 'DTEND'
12-
data[:end_time] = Time.parse(value)
12+
data[:end_time] = _parse_in_tzid(value, tzid)
1313
when 'EXDATE'
1414
data[:extimes] ||= []
15-
data[:extimes] += value.split(',').map{|v| Time.parse(v)}
15+
data[:extimes] += value.split(',').map do |v|
16+
_parse_in_tzid(v, tzid)
17+
end
1618
when 'DURATION'
1719
data[:duration] # FIXME
1820
when 'RRULE'
@@ -22,6 +24,14 @@ def self.schedule_from_ical(ical_string, options = {})
2224
Schedule.from_hash data
2325
end
2426

27+
def self._parse_in_tzid(value, tzid)
28+
t = Time.parse(value)
29+
if tzid
30+
t = t.in_time_zone(ActiveSupport::TimeZone[tzid.split("=")[1]])
31+
end
32+
t
33+
end
34+
2535
def self.rule_from_ical(ical)
2636
params = { validations: { } }
2737

spec/examples/from_ical_spec.rb

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,22 @@ module IceCube
9494

9595
end
9696

97-
describe Schedule, 'from_ical' do
97+
describe Schedule, 'from_ical', system_time_zone: "America/Chicago" do
9898

9999
ical_string = <<-ICAL.gsub(/^\s*/, '')
100100
DTSTART:20130314T201500Z
101101
DTEND:20130314T201545Z
102102
RRULE:FREQ=WEEKLY;BYDAY=TH;UNTIL=20130531T100000Z
103103
ICAL
104104

105-
ical_string_woth_multiple_exdates = <<-ICAL.gsub(/^\s*/, '')
105+
ical_string_with_time_zones = <<-ICAL.gsub(/^\s*/,'')
106+
DTSTART;TZID=America/Denver:20130731T143000
107+
DTEND:20130731T153000
108+
RRULE:FREQ=WEEKLY
109+
EXDATE;TZID=America/Chicago:20130823T143000
110+
ICAL
111+
112+
ical_string_with_multiple_exdates = <<-ICAL.gsub(/^\s*/, '')
106113
DTSTART;TZID=America/Denver:20130731T143000
107114
DTEND;TZID=America/Denver:20130731T153000
108115
RRULE:FREQ=WEEKLY;UNTIL=20140730T203000Z;BYDAY=MO,WE,FR
@@ -125,6 +132,20 @@ def sorted_ical(ical)
125132
it "loads an ICAL string" do
126133
expect(IceCube::Schedule.from_ical(ical_string)).to be_a(IceCube::Schedule)
127134
end
135+
describe "parsing time zones" do
136+
it "sets the time zone of the start time" do
137+
schedule = IceCube::Schedule.from_ical(ical_string_with_time_zones)
138+
expect(schedule.start_time.time_zone).to eq ActiveSupport::TimeZone.new("America/Denver")
139+
end
140+
it "uses the system time if a time zone is not explicity provided" do
141+
schedule = IceCube::Schedule.from_ical(ical_string_with_time_zones)
142+
expect(schedule.end_time).not_to respond_to :time_zone
143+
end
144+
it "sets the time zone of the exception times" do
145+
schedule = IceCube::Schedule.from_ical(ical_string_with_time_zones)
146+
expect(schedule.exception_times[0].time_zone).to eq ActiveSupport::TimeZone.new("America/Chicago")
147+
end
148+
end
128149
end
129150

130151
describe "daily frequency" do
@@ -235,7 +256,6 @@ def sorted_ical(ical)
235256
describe 'monthly frequency' do
236257
it 'matches simple monthly' do
237258
start_time = Time.now
238-
239259
schedule = IceCube::Schedule.new(start_time)
240260
schedule.add_recurrence_rule(IceCube::Rule.monthly)
241261

@@ -359,7 +379,7 @@ def sorted_ical(ical)
359379
end
360380

361381
it 'handles multiple EXDATE lines' do
362-
schedule = IceCube::Schedule.from_ical ical_string_woth_multiple_exdates
382+
schedule = IceCube::Schedule.from_ical ical_string_with_multiple_exdates
363383
schedule.exception_times.count.should == 3
364384
end
365385
end

spec/examples/hourly_rule_spec.rb

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@ module IceCube
3939
end
4040

4141
it 'should not skip times in DST end hour' do
42-
schedule = Schedule.new(t0 = Time.local(2013, 11, 3, 0, 0, 0))
42+
tz = ActiveSupport::TimeZone["America/Vancouver"]
43+
schedule = Schedule.new(t0 = tz.local(2013, 11, 3, 0, 0, 0))
4344
schedule.add_recurrence_rule Rule.hourly
44-
schedule.first(4).should == [
45-
Time.local(2013, 11, 3, 0, 0, 0), # -0700
46-
Time.local(2013, 11, 3, 1, 0, 0) - ONE_HOUR, # -0700
47-
Time.local(2013, 11, 3, 1, 0, 0), # -0800
48-
Time.local(2013, 11, 3, 2, 0, 0), # -0800
45+
expect(schedule.first(4)).to eq [
46+
tz.local(2013, 11, 3, 0, 0, 0), # -0700
47+
tz.local(2013, 11, 3, 1, 0, 0), # -0700
48+
tz.local(2013, 11, 3, 2, 0, 0) - ONE_HOUR, # -0800
49+
tz.local(2013, 11, 3, 2, 0, 0), # -0800
4950
]
5051
end
5152

0 commit comments

Comments
 (0)