diff --git a/lib/ri_cal/component/t_z_info_timezone.rb b/lib/ri_cal/component/t_z_info_timezone.rb index d852e242..616252c1 100644 --- a/lib/ri_cal/component/t_z_info_timezone.rb +++ b/lib/ri_cal/component/t_z_info_timezone.rb @@ -66,13 +66,21 @@ def export_to(export_stream) class Periods #:nodoc: all def initialize - @dst_period = @std_period = @previous_period = nil + @daylight_period = @standard_period = @previous_period = nil end def empty? @periods.nil? || @periods.empty? end + def has_standard? + !@standard_period.nil? + end + + def has_daylight? + !@daylight_period.nil? + end + def daylight_period(this_period, previous_period) @daylight_period ||= Period.new("DAYLIGHT", this_period, previous_period) end @@ -142,10 +150,14 @@ def export_utc_to(export_stream, utc_start, utc_end) #:nodoc: #start with the period before the one containing utc_start prev_period = period.utc_start && tzinfo_timezone.period_for_utc(period.utc_start - 1) period = prev_period if prev_period - while period && period.utc_start && period.utc_start < utc_end + while period && period.utc_start && period.utc_start <= utc_end periods.add_period(period) + prev_period = period period = period.utc_end && tzinfo_timezone.period_for_utc(period.utc_end + 1) end + if period && prev_period && period.dst? != prev_period.dst? && !(periods.has_daylight? && periods.has_standard?) + periods.add_period(period) + end periods.add_period(initial_period, :force) if periods.empty? periods.export_to(export_stream) export_stream.puts "END:VTIMEZONE\n" diff --git a/spec/ri_cal/component/t_z_info_timezone_spec.rb b/spec/ri_cal/component/t_z_info_timezone_spec.rb index 0f709280..1348689b 100644 --- a/spec/ri_cal/component/t_z_info_timezone_spec.rb +++ b/spec/ri_cal/component/t_z_info_timezone_spec.rb @@ -36,6 +36,62 @@ ENDDATA end + it "should produce an rfc representation that Outlook will not barf on" do + tz = RiCal::Component::TZInfoTimezone.new(TZInfo::Timezone.get("America/New_York")) + local_first = DateTime.parse("Apr 10, 2007") + local_last = DateTime.parse("Apr 16, 2007") + utc_first = tz.local_to_utc(local_first) + utc_last = tz.local_to_utc(local_last) + rez = tz.to_rfc2445_string(utc_first, utc_last) + rez.should == <<-ENDDATA +BEGIN:VTIMEZONE +TZID;X-RICAL-TZSOURCE=TZINFO:America/New_York +BEGIN:DAYLIGHT +DTSTART:20070311T020000 +RDATE:20070311T020000 +TZOFFSETFROM:-0500 +TZOFFSETTO:-0400 +TZNAME:EDT +END:DAYLIGHT +BEGIN:STANDARD +DTSTART:20071104T020000 +RDATE:20071104T020000 +TZOFFSETFROM:-0400 +TZOFFSETTO:-0500 +TZNAME:EST +END:STANDARD +END:VTIMEZONE +ENDDATA + end + + it "should produce an rfc representation that Outlook will not barf on at DST switch" do + tz = RiCal::Component::TZInfoTimezone.new(TZInfo::Timezone.get("America/New_York")) + local_first = DateTime.parse("Mar 11, 2007 03:00:00 AM") + local_last = DateTime.parse("Mar 11, 2007 03:00:00 AM") + utc_first = tz.local_to_utc(local_first) + utc_last = tz.local_to_utc(local_last) + rez = tz.to_rfc2445_string(utc_first, utc_last) + rez.should == <<-ENDDATA +BEGIN:VTIMEZONE +TZID;X-RICAL-TZSOURCE=TZINFO:America/New_York +BEGIN:DAYLIGHT +DTSTART:20070311T020000 +RDATE:20070311T020000 +TZOFFSETFROM:-0500 +TZOFFSETTO:-0400 +TZNAME:EDT +END:DAYLIGHT +BEGIN:STANDARD +DTSTART:20071104T020000 +RDATE:20071104T020000 +TZOFFSETFROM:-0400 +TZOFFSETTO:-0500 +TZNAME:EST +END:STANDARD +END:VTIMEZONE +ENDDATA + end + TZInfo::Timezone.all_identifiers.each do |tz| context "TZInfo timezone #{tz}" do before(:each) do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f61548df..6570bba1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,6 +4,7 @@ require 'cgi' require 'tzinfo' +alias :context :describe module Kernel if ENV.keys.find {|env_var| env_var.match(/^TM_/)}