diff --git a/lib/ice_cube/parsers/ical_parser.rb b/lib/ice_cube/parsers/ical_parser.rb index 2e1e2f05..437efac9 100644 --- a/lib/ice_cube/parsers/ical_parser.rb +++ b/lib/ice_cube/parsers/ical_parser.rb @@ -7,12 +7,14 @@ def self.schedule_from_ical(ical_string, options = {}) (property, tzid) = property.split(';') case property when 'DTSTART' - data[:start_time] = Time.parse(value) + data[:start_time] = _parse_in_tzid(value, tzid) when 'DTEND' - data[:end_time] = Time.parse(value) + data[:end_time] = _parse_in_tzid(value, tzid) when 'EXDATE' data[:extimes] ||= [] - data[:extimes] += value.split(',').map{|v| Time.parse(v)} + data[:extimes] += value.split(',').map do |v| + _parse_in_tzid(v, tzid) + end when 'DURATION' data[:duration] # FIXME when 'RRULE' @@ -23,6 +25,14 @@ def self.schedule_from_ical(ical_string, options = {}) Schedule.from_hash data end + def self._parse_in_tzid(value, tzid) + time_parser = Time + if tzid + time_parser = ActiveSupport::TimeZone.new(tzid.split('=')[1]) || Time + end + time_parser.parse(value) + end + def self.rule_from_ical(ical) params = { validations: { } } diff --git a/spec/examples/from_ical_spec.rb b/spec/examples/from_ical_spec.rb index a46cb3f1..3694bdc2 100644 --- a/spec/examples/from_ical_spec.rb +++ b/spec/examples/from_ical_spec.rb @@ -94,7 +94,7 @@ module IceCube end - describe Schedule, 'from_ical' do + describe Schedule, 'from_ical', system_time_zone: "America/Chicago" do ical_string = <<-ICAL.gsub(/^\s*/, '') DTSTART:20130314T201500Z @@ -102,7 +102,14 @@ module IceCube RRULE:FREQ=WEEKLY;BYDAY=TH;UNTIL=20130531T100000Z ICAL - ical_string_with_multiple_exdates = <<-ICAL.gsub(/^\s*/, '') + ical_string_with_time_zones = <<-ICAL.gsub(/^\s*/,'') + DTSTART;TZID=America/Denver:20130731T143000 + DTEND:20130731T153000 + RRULE:FREQ=WEEKLY + EXDATE;TZID=America/Chicago:20130823T143000 + ICAL + + ical_string_with_multiple_exdates = <<-ICAL.gsub(/^\s*/, '') DTSTART;TZID=America/Denver:20130731T143000 DTEND;TZID=America/Denver:20130731T153000 RRULE:FREQ=WEEKLY;UNTIL=20140730T203000Z;BYDAY=MO,WE,FR @@ -130,6 +137,28 @@ def sorted_ical(ical) it "loads an ICAL string" do expect(IceCube::Schedule.from_ical(ical_string)).to be_a(IceCube::Schedule) end + + describe "parsing time zones" do + it "sets the time zone of the start time" do + schedule = IceCube::Schedule.from_ical(ical_string_with_time_zones) + expect(schedule.start_time.time_zone).to eq ActiveSupport::TimeZone.new("America/Denver") + end + + it "uses the system time if a time zone is not explicity provided" do + schedule = IceCube::Schedule.from_ical(ical_string_with_time_zones) + expect(schedule.end_time).not_to respond_to :time_zone + end + + it "sets the time zone of the exception times" do + schedule = IceCube::Schedule.from_ical(ical_string_with_time_zones) + expect(schedule.exception_times[0].time_zone).to eq ActiveSupport::TimeZone.new("America/Chicago") + end + + it "adding the offset doesnt also change the time" do + schedule = IceCube::Schedule.from_ical(ical_string_with_time_zones) + expect(schedule.exception_times[0].hour).to eq 14 + end + end end describe "daily frequency" do @@ -240,7 +269,6 @@ def sorted_ical(ical) describe 'monthly frequency' do it 'matches simple monthly' do start_time = Time.now - schedule = IceCube::Schedule.new(start_time) schedule.add_recurrence_rule(IceCube::Rule.monthly) diff --git a/spec/examples/hourly_rule_spec.rb b/spec/examples/hourly_rule_spec.rb index 854cf990..199ed514 100644 --- a/spec/examples/hourly_rule_spec.rb +++ b/spec/examples/hourly_rule_spec.rb @@ -39,13 +39,14 @@ module IceCube end it 'should not skip times in DST end hour' do - schedule = Schedule.new(t0 = Time.local(2013, 11, 3, 0, 0, 0)) + tz = ActiveSupport::TimeZone["America/Vancouver"] + schedule = Schedule.new(t0 = tz.local(2013, 11, 3, 0, 0, 0)) schedule.add_recurrence_rule Rule.hourly - schedule.first(4).should == [ - Time.local(2013, 11, 3, 0, 0, 0), # -0700 - Time.local(2013, 11, 3, 1, 0, 0) - ONE_HOUR, # -0700 - Time.local(2013, 11, 3, 1, 0, 0), # -0800 - Time.local(2013, 11, 3, 2, 0, 0), # -0800 + expect(schedule.first(4)).to eq [ + tz.local(2013, 11, 3, 0, 0, 0), # -0700 + tz.local(2013, 11, 3, 1, 0, 0), # -0700 + tz.local(2013, 11, 3, 2, 0, 0) - ONE_HOUR, # -0800 + tz.local(2013, 11, 3, 2, 0, 0), # -0800 ] end