time_zone_test.rb 8.4 KB
Newer Older
1
require 'abstract_unit'
2 3

class TimeZoneTest < Test::Unit::TestCase
4 5 6 7 8 9 10 11 12
  
  uses_tzinfo 'TestTimeZoneCalculations' do
    
    def test_utc_to_local
      silence_warnings do # silence warnings raised by tzinfo gem
        zone = TimeZone['Eastern Time (US & Canada)']
        assert_equal Time.utc(1999, 12, 31, 19), zone.utc_to_local(Time.utc(2000, 1)) # standard offset -0500
        assert_equal Time.utc(2000, 6, 30, 20), zone.utc_to_local(Time.utc(2000, 7)) # dst offset -0400
      end
13
    end
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
  
    def test_local_to_utc
      silence_warnings do # silence warnings raised by tzinfo gem
        zone = TimeZone['Eastern Time (US & Canada)']
        assert_equal Time.utc(2000, 1, 1, 5), zone.local_to_utc(Time.utc(2000, 1)) # standard offset -0500
        assert_equal Time.utc(2000, 7, 1, 4), zone.local_to_utc(Time.utc(2000, 7)) # dst offset -0400
      end
    end
    
    def test_period_for_local
      silence_warnings do # silence warnings raised by tzinfo gem
        zone = TimeZone['Eastern Time (US & Canada)']
        assert_instance_of TZInfo::TimezonePeriod, zone.period_for_local(Time.utc(2000))
      end
    end
    
    TimeZone::MAPPING.keys.each do |name|
      define_method("test_map_#{name.downcase.gsub(/[^a-z]/, '_')}_to_tzinfo") do
        silence_warnings do # silence warnings raised by tzinfo gem
          zone = TimeZone[name]
          assert zone.tzinfo.respond_to?(:period_for_local)
        end
      end
37
    end
38

39 40 41 42 43 44 45 46
    def test_from_integer_to_map
      assert_instance_of TimeZone, TimeZone[-28800] # PST
    end

    def test_from_duration_to_map
      assert_instance_of TimeZone, TimeZone[-480.minutes] # PST
    end

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
    TimeZone.all.each do |zone|
      name = zone.name.downcase.gsub(/[^a-z]/, '_')
      define_method("test_from_#{name}_to_map") do
        silence_warnings do # silence warnings raised by tzinfo gem
          assert_instance_of TimeZone, TimeZone[zone.name]
        end
      end

      define_method("test_utc_offset_for_#{name}") do
        silence_warnings do # silence warnings raised by tzinfo gem
          period = zone.tzinfo.period_for_utc(Time.utc(2006,1,1,0,0,0))
          assert_equal period.utc_offset, zone.utc_offset
        end
      end
    end
62

63 64
    uses_mocha 'TestTimeZoneNowAndToday' do
      def test_now
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
        with_env_tz 'US/Eastern' do
          Time.stubs(:now).returns(Time.local(2000))
          zone = TimeZone['Eastern Time (US & Canada)']
          assert_instance_of ActiveSupport::TimeWithZone, zone.now
          assert_equal Time.utc(2000,1,1,5), zone.now.utc
          assert_equal Time.utc(2000), zone.now.time
          assert_equal zone, zone.now.time_zone
        end
      end
      
      def test_now_enforces_spring_dst_rules
        with_env_tz 'US/Eastern' do
          Time.stubs(:now).returns(Time.local(2006,4,2,2)) # 2AM springs forward to 3AM
          zone = TimeZone['Eastern Time (US & Canada)']
          assert_equal Time.utc(2006,4,2,3), zone.now.time
          assert_equal true, zone.now.dst?
        end
      end
      
      def test_now_enforces_fall_dst_rules
        with_env_tz 'US/Eastern' do
86
          Time.stubs(:now).returns(Time.at(1162098000)) # equivalent to 1AM DST
87
          zone = TimeZone['Eastern Time (US & Canada)']
88
          assert_equal Time.utc(2006,10,29,1), zone.now.time
89 90
          assert_equal true, zone.now.dst?
        end
91 92 93 94 95 96 97 98 99
      end
    
      def test_today
        TZInfo::DataTimezone.any_instance.stubs(:now).returns(Time.utc(2000))
        assert_equal Date.new(2000), TimeZone['Eastern Time (US & Canada)'].today
      end
    end
  end
  
100
  def test_formatted_offset_positive
101 102 103
    zone = TimeZone['Moscow']
    assert_equal "+03:00", zone.formatted_offset
    assert_equal "+0300", zone.formatted_offset(false)
104
  end
105
  
106
  def test_formatted_offset_negative
107 108 109
    zone = TimeZone['Eastern Time (US & Canada)']
    assert_equal "-05:00", zone.formatted_offset
    assert_equal "-0500", zone.formatted_offset(false)
110
  end
111
  
112 113 114 115 116 117
  def test_formatted_offset_zero
    zone = TimeZone['London']
    assert_equal "+00:00", zone.formatted_offset
    assert_equal "UTC", zone.formatted_offset(true, 'UTC')
  end
  
118
  def test_zone_compare
119 120
    zone1 = TimeZone['Central Time (US & Canada)'] # offset -0600
    zone2 = TimeZone['Eastern Time (US & Canada)'] # offset -0500
121 122 123 124
    assert zone1 < zone2
    assert zone2 > zone1
    assert zone1 == zone1
  end
125
  
126
  def test_to_s
127
    assert_equal "(UTC+03:00) Moscow", TimeZone['Moscow'].to_s
128
  end
129
  
130 131 132 133 134 135
  def test_all_sorted
    all = TimeZone.all
    1.upto( all.length-1 ) do |i|
      assert all[i-1] < all[i]
    end
  end
136
  
137 138
  def test_index
    assert_nil TimeZone["bogus"]
139 140
    assert_instance_of TimeZone, TimeZone["Central Time (US & Canada)"]
    assert_instance_of TimeZone, TimeZone[8]
141
    assert_raises(ArgumentError) { TimeZone[false] }
142
  end
143
  
144
  def test_new
145
    assert_equal TimeZone["Central Time (US & Canada)"], TimeZone.new("Central Time (US & Canada)")
146
  end
147 148 149 150 151
  
  def test_us_zones
    assert TimeZone.us_zones.include?(TimeZone["Hawaii"])
    assert !TimeZone.us_zones.include?(TimeZone["Kuala Lumpur"])
  end 
152
  
153 154
  def test_local
    time = TimeZone["Hawaii"].local(2007, 2, 5, 15, 30, 45)
155 156 157
    assert_equal Time.utc(2007, 2, 5, 15, 30, 45), time.time
    assert_equal TimeZone["Hawaii"], time.time_zone
  end
158
  
G
Geoff Buesing 已提交
159 160 161 162 163 164 165 166
  def test_local_with_old_date
    silence_warnings do # silence warnings raised by tzinfo gem
      time = TimeZone["Hawaii"].local(1850, 2, 5, 15, 30, 45)
      assert_equal [45,30,15,5,2,1850], time.to_a[0,6]
      assert_equal TimeZone["Hawaii"], time.time_zone
    end
  end
  
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
  def test_local_enforces_spring_dst_rules
    zone = TimeZone['Eastern Time (US & Canada)']
    twz = zone.local(2006,4,2,1,59,59) # 1 second before DST start
    assert_equal Time.utc(2006,4,2,1,59,59), twz.time
    assert_equal Time.utc(2006,4,2,6,59,59), twz.utc
    assert_equal false, twz.dst?
    assert_equal 'EST', twz.zone
    twz2 = zone.local(2006,4,2,2) # 2AM does not exist because at 2AM, time springs forward to 3AM
    assert_equal Time.utc(2006,4,2,3), twz2.time # twz is created for 3AM
    assert_equal Time.utc(2006,4,2,7), twz2.utc
    assert_equal true, twz2.dst?
    assert_equal 'EDT', twz2.zone
    twz3 = zone.local(2006,4,2,2,30) # 2:30AM does not exist because at 2AM, time springs forward to 3AM
    assert_equal Time.utc(2006,4,2,3,30), twz3.time # twz is created for 3:30AM
    assert_equal Time.utc(2006,4,2,7,30), twz3.utc
    assert_equal true, twz3.dst?
    assert_equal 'EDT', twz3.zone
  end
  
  def test_local_enforces_fall_dst_rules
    # 1AM during fall DST transition is ambiguous, it could be either DST or non-DST 1AM
    # Mirroring Time.local behavior, this method selects the DST time
    zone = TimeZone['Eastern Time (US & Canada)']
    twz = zone.local(2006,10,29,1)
    assert_equal Time.utc(2006,10,29,1), twz.time
    assert_equal Time.utc(2006,10,29,5), twz.utc
    assert_equal true, twz.dst? 
    assert_equal 'EDT', twz.zone
  end
196 197 198 199 200 201 202 203 204 205 206 207
  
  def test_at
    zone = TimeZone['Eastern Time (US & Canada)']
    secs = 946684800.0
    twz = zone.at(secs)
    assert_equal Time.utc(1999,12,31,19), twz.time
    assert_equal Time.utc(2000), twz.utc
    assert_equal zone, twz.time_zone
    assert_equal secs, twz.to_f
  end
  
  def test_at_with_old_date
G
Geoff Buesing 已提交
208 209
    zone = TimeZone['Eastern Time (US & Canada)']
    secs = DateTime.civil(1850).to_f
210
    twz = zone.at(secs)
G
Geoff Buesing 已提交
211
    assert_equal [1850, 1, 1, 0], [twz.utc.year, twz.utc.mon, twz.utc.day, twz.utc.hour]
212 213 214
    assert_equal zone, twz.time_zone
    assert_equal secs, twz.to_f
  end
G
Geoff Buesing 已提交
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
  
  def test_parse
    zone = TimeZone['Eastern Time (US & Canada)']
    twz = zone.parse('1999-12-31 19:00:00')
    assert_equal Time.utc(1999,12,31,19), twz.time
    assert_equal Time.utc(2000), twz.utc
    assert_equal zone, twz.time_zone
  end
  
  def test_parse_with_old_date
    silence_warnings do # silence warnings raised by tzinfo gem
      zone = TimeZone['Eastern Time (US & Canada)']
      twz = zone.parse('1850-12-31 19:00:00')
      assert_equal [0,0,19,31,12,1850], twz.to_a[0,6]
      assert_equal zone, twz.time_zone
    end
  end
  
  uses_mocha 'TestParseWithIncompleteDate' do
    def test_parse_with_incomplete_date
      zone = TimeZone['Eastern Time (US & Canada)']
      zone.stubs(:now).returns zone.local(1999,12,31)
      twz = zone.parse('19:00:00')
      assert_equal Time.utc(1999,12,31,19), twz.time
    end
  end
241

242 243 244 245 246 247 248 249
  protected
    def with_env_tz(new_tz = 'US/Eastern')
      old_tz, ENV['TZ'] = ENV['TZ'], new_tz
      yield
    ensure
      old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
    end  
end