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

class TimeZoneTest < Test::Unit::TestCase
4
    
5 6 7 8 9
  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
10
    end
11 12 13 14 15 16 17 18 19
  end

  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
20
  
21 22 23 24
  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))
25
    end
26 27 28 29
  end
  
  TimeZone::MAPPING.keys.each do |name|
    define_method("test_map_#{name.downcase.gsub(/[^a-z]/, '_')}_to_tzinfo") do
30
      silence_warnings do # silence warnings raised by tzinfo gem
31 32
        zone = TimeZone[name]
        assert zone.tzinfo.respond_to?(:period_for_local)
33
      end
34
    end
35
  end
36

37 38 39
  def test_from_integer_to_map
    assert_instance_of TimeZone, TimeZone[-28800] # PST
  end
40

41 42 43
  def test_from_duration_to_map
    assert_instance_of TimeZone, TimeZone[-480.minutes] # PST
  end
44

45 46 47 48 49
  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]
50
      end
51
    end
52

53 54 55 56
    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
57 58
      end
    end
59
  end
60

61 62 63 64 65 66 67 68 69
  uses_mocha 'TestTimeZoneNowAndToday' do
    def test_now
      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
70
      end
71
    end
72
    
73 74 75 76 77 78
    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?
79 80 81
      end
    end
    
82 83 84 85 86 87
    def test_now_enforces_fall_dst_rules
      with_env_tz 'US/Eastern' do
        Time.stubs(:now).returns(Time.at(1162098000)) # equivalent to 1AM DST
        zone = TimeZone['Eastern Time (US & Canada)']
        assert_equal Time.utc(2006,10,29,1), zone.now.time
        assert_equal true, zone.now.dst?
88 89
      end
    end
90 91 92 93 94 95 96 97 98 99
  
    def test_today
      Time.stubs(:now).returns(Time.utc(2000, 1, 1, 4, 59, 59)) # 1 sec before midnight Jan 1 EST
      assert_equal Date.new(1999, 12, 31), TimeZone['Eastern Time (US & Canada)'].today
      Time.stubs(:now).returns(Time.utc(2000, 1, 1, 5)) # midnight Jan 1 EST
      assert_equal Date.new(2000, 1, 1), TimeZone['Eastern Time (US & Canada)'].today
      Time.stubs(:now).returns(Time.utc(2000, 1, 2, 4, 59, 59)) # 1 sec before midnight Jan 2 EST
      assert_equal Date.new(2000, 1, 1), TimeZone['Eastern Time (US & Canada)'].today
      Time.stubs(:now).returns(Time.utc(2000, 1, 2, 5)) # midnight Jan 2 EST
      assert_equal Date.new(2000, 1, 2), TimeZone['Eastern Time (US & Canada)'].today
100
    end
101 102 103 104 105 106 107
  end
  
  def test_local
    silence_warnings do # silence warnings raised by tzinfo gem
      time = TimeZone["Hawaii"].local(2007, 2, 5, 15, 30, 45)
      assert_equal Time.utc(2007, 2, 5, 15, 30, 45), time.time
      assert_equal TimeZone["Hawaii"], time.time_zone
108
    end
109
  end
110

111 112 113 114 115
  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
116
    end
117
  end
118

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
  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
148

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
  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
    zone = TimeZone['Eastern Time (US & Canada)']
    secs = DateTime.civil(1850).to_f
    twz = zone.at(secs)
    assert_equal [1850, 1, 1, 0], [twz.utc.year, twz.utc.mon, twz.utc.day, twz.utc.hour]
    assert_equal zone, twz.time_zone
    assert_equal secs, twz.to_f
  end

  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

176 177 178 179 180 181 182 183
  def test_parse_string_with_timezone
    (-11..13).each do |timezone_offset|
      zone = TimeZone[timezone_offset]
      twz = zone.parse('1999-12-31 19:00:00')
      assert_equal twz, zone.parse(twz.to_s)
    end
  end

184 185
  def test_parse_with_old_date
    silence_warnings do # silence warnings raised by tzinfo gem
186
      zone = TimeZone['Eastern Time (US & Canada)']
187 188
      twz = zone.parse('1850-12-31 19:00:00')
      assert_equal [0,0,19,31,12,1850], twz.to_a[0,6]
189 190
      assert_equal zone, twz.time_zone
    end
191
  end
192

193 194
  uses_mocha 'TestParseWithIncompleteDate' do
    def test_parse_with_incomplete_date
195
      zone = TimeZone['Eastern Time (US & Canada)']
196 197
      zone.stubs(:now).returns zone.local(1999,12,31)
      twz = zone.parse('19:00:00')
198
      assert_equal Time.utc(1999,12,31,19), twz.time
199
    end
200 201 202 203 204 205 206 207
  end
  
  def test_utc_offset_lazy_loaded_from_tzinfo_when_not_passed_in_to_initialize
    silence_warnings do # silence warnings raised by tzinfo gem
      tzinfo = TZInfo::Timezone.get('America/New_York')
      zone = TimeZone.create(tzinfo.name, nil, tzinfo)
      assert_equal nil, zone.instance_variable_get('@utc_offset')
      assert_equal(-18_000, zone.utc_offset)
208
    end
209 210
  end
  
211
  def test_formatted_offset_positive
212 213 214
    zone = TimeZone['Moscow']
    assert_equal "+03:00", zone.formatted_offset
    assert_equal "+0300", zone.formatted_offset(false)
215
  end
216
  
217
  def test_formatted_offset_negative
218 219 220
    zone = TimeZone['Eastern Time (US & Canada)']
    assert_equal "-05:00", zone.formatted_offset
    assert_equal "-0500", zone.formatted_offset(false)
221
  end
222
  
223 224 225 226 227 228
  def test_formatted_offset_zero
    zone = TimeZone['London']
    assert_equal "+00:00", zone.formatted_offset
    assert_equal "UTC", zone.formatted_offset(true, 'UTC')
  end
  
229
  def test_zone_compare
230 231
    zone1 = TimeZone['Central Time (US & Canada)'] # offset -0600
    zone2 = TimeZone['Eastern Time (US & Canada)'] # offset -0500
232 233 234 235
    assert zone1 < zone2
    assert zone2 > zone1
    assert zone1 == zone1
  end
236
  
237
  def test_to_s
238
    assert_equal "(UTC+03:00) Moscow", TimeZone['Moscow'].to_s
239
  end
240
  
241 242 243 244 245 246
  def test_all_sorted
    all = TimeZone.all
    1.upto( all.length-1 ) do |i|
      assert all[i-1] < all[i]
    end
  end
247
  
248 249
  def test_index
    assert_nil TimeZone["bogus"]
250 251
    assert_instance_of TimeZone, TimeZone["Central Time (US & Canada)"]
    assert_instance_of TimeZone, TimeZone[8]
252
    assert_raises(ArgumentError) { TimeZone[false] }
253
  end
254
  
255
  def test_new
256
    assert_equal TimeZone["Central Time (US & Canada)"], TimeZone.new("Central Time (US & Canada)")
257
  end
258 259 260 261 262
  
  def test_us_zones
    assert TimeZone.us_zones.include?(TimeZone["Hawaii"])
    assert !TimeZone.us_zones.include?(TimeZone["Kuala Lumpur"])
  end 
263
  
264 265 266 267 268 269 270 271
  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