time_zone_test.rb 10.7 KB
Newer Older
1
require 'abstract_unit'
2
require 'active_support/time'
3 4

class TimeZoneTest < Test::Unit::TestCase
5
  def test_utc_to_local
6 7 8
    zone = ActiveSupport::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
9 10 11
  end

  def test_local_to_utc
12 13 14
    zone = ActiveSupport::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
15
  end
16

17
  def test_period_for_local
18 19
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
    assert_instance_of TZInfo::TimezonePeriod, zone.period_for_local(Time.utc(2000))
20
  end
21 22

  ActiveSupport::TimeZone::MAPPING.keys.each do |name|
23
    define_method("test_map_#{name.downcase.gsub(/[^a-z]/, '_')}_to_tzinfo") do
24 25
      zone = ActiveSupport::TimeZone[name]
      assert zone.tzinfo.respond_to?(:period_for_local)
26
    end
27
  end
28

29
  def test_from_integer_to_map
30
    assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone[-28800] # PST
31
  end
32

33
  def test_from_duration_to_map
34
    assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone[-480.minutes] # PST
35
  end
36

37
  ActiveSupport::TimeZone.all.each do |zone|
38 39
    name = zone.name.downcase.gsub(/[^a-z]/, '_')
    define_method("test_from_#{name}_to_map") do
40
      assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone[zone.name]
41
    end
42

43
    define_method("test_utc_offset_for_#{name}") do
44 45
      period = zone.tzinfo.current_period
      assert_equal period.utc_offset, zone.utc_offset
46
    end
47
  end
48

49 50 51 52 53 54 55 56
  def test_now
    with_env_tz 'US/Eastern' do
      Time.stubs(:now).returns(Time.local(2000))
      zone = ActiveSupport::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
57
    end
58
  end
59

60 61 62 63 64 65
  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 = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
      assert_equal Time.utc(2006,4,2,3), zone.now.time
      assert_equal true, zone.now.dst?
66
    end
67
  end
68

69 70 71 72 73 74
  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 = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
      assert_equal Time.utc(2006,10,29,1), zone.now.time
      assert_equal true, zone.now.dst?
75
    end
76
  end
77

78 79 80 81 82 83 84 85 86
  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), ActiveSupport::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), ActiveSupport::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), ActiveSupport::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), ActiveSupport::TimeZone['Eastern Time (US & Canada)'].today
87
  end
88

89
  def test_local
90 91 92
    time = ActiveSupport::TimeZone["Hawaii"].local(2007, 2, 5, 15, 30, 45)
    assert_equal Time.utc(2007, 2, 5, 15, 30, 45), time.time
    assert_equal ActiveSupport::TimeZone["Hawaii"], time.time_zone
93
  end
94

95
  def test_local_with_old_date
96 97 98
    time = ActiveSupport::TimeZone["Hawaii"].local(1850, 2, 5, 15, 30, 45)
    assert_equal [45,30,15,5,2,1850], time.to_a[0,6]
    assert_equal ActiveSupport::TimeZone["Hawaii"], time.time_zone
99
  end
100

101
  def test_local_enforces_spring_dst_rules
102
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
    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
123
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
124 125 126
    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
127
    assert_equal true, twz.dst?
128 129
    assert_equal 'EDT', twz.zone
  end
130

131
  def test_at
132
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
133 134 135 136 137 138 139 140 141
    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
142
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
143 144 145 146 147 148 149 150
    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
151
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
152 153 154 155 156 157
    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

158 159
  def test_parse_string_with_timezone
    (-11..13).each do |timezone_offset|
160
      zone = ActiveSupport::TimeZone[timezone_offset]
161 162 163 164 165
      twz = zone.parse('1999-12-31 19:00:00')
      assert_equal twz, zone.parse(twz.to_s)
    end
  end

166
  def test_parse_with_old_date
167 168 169 170
    zone = ActiveSupport::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
171
  end
172

173
  def test_parse_far_future_date_with_time_zone_offset_in_string
174 175 176 177
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
    twz = zone.parse('2050-12-31 19:00:00 -10:00') # i.e., 2050-01-01 05:00:00 UTC
    assert_equal [0,0,0,1,1,2051], twz.to_a[0,6]
    assert_equal zone, twz.time_zone
178
  end
179

180
  def test_parse_returns_nil_when_string_without_date_information_is_passed_in
181 182 183
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
    assert_nil zone.parse('foobar')
    assert_nil zone.parse('   ')
184
  end
185

186 187 188 189 190
  def test_parse_with_incomplete_date
    zone = ActiveSupport::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
191
  end
192

193
  def test_utc_offset_lazy_loaded_from_tzinfo_when_not_passed_in_to_initialize
194 195 196 197
    tzinfo = TZInfo::Timezone.get('America/New_York')
    zone = ActiveSupport::TimeZone.create(tzinfo.name, nil, tzinfo)
    assert_equal nil, zone.instance_variable_get('@utc_offset')
    assert_equal(-18_000, zone.utc_offset)
198
  end
199

200
  def test_seconds_to_utc_offset_with_colon
J
Jeremy Kemper 已提交
201 202 203
    assert_equal "-06:00", ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600)
    assert_equal "+00:00", ActiveSupport::TimeZone.seconds_to_utc_offset(0)
    assert_equal "+05:00", ActiveSupport::TimeZone.seconds_to_utc_offset(18_000)
204 205 206
  end

  def test_seconds_to_utc_offset_without_colon
J
Jeremy Kemper 已提交
207 208 209
    assert_equal "-0600", ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600, false)
    assert_equal "+0000", ActiveSupport::TimeZone.seconds_to_utc_offset(0, false)
    assert_equal "+0500", ActiveSupport::TimeZone.seconds_to_utc_offset(18_000, false)
210
  end
211 212 213 214 215 216
  
  def test_seconds_to_utc_offset_with_negative_offset
    assert_equal "-01:00", ActiveSupport::TimeZone.seconds_to_utc_offset(-3_600)
    assert_equal "-00:59", ActiveSupport::TimeZone.seconds_to_utc_offset(-3_599)
    assert_equal "-05:30", ActiveSupport::TimeZone.seconds_to_utc_offset(-19_800)
  end
217

218
  def test_formatted_offset_positive
219
    zone = ActiveSupport::TimeZone['Moscow']
220 221
    assert_equal "+03:00", zone.formatted_offset
    assert_equal "+0300", zone.formatted_offset(false)
222
  end
223

224
  def test_formatted_offset_negative
225
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
226 227
    assert_equal "-05:00", zone.formatted_offset
    assert_equal "-0500", zone.formatted_offset(false)
228
  end
229

230
  def test_formatted_offset_zero
231
    zone = ActiveSupport::TimeZone['London']
232 233 234
    assert_equal "+00:00", zone.formatted_offset
    assert_equal "UTC", zone.formatted_offset(true, 'UTC')
  end
235

236
  def test_zone_compare
237 238
    zone1 = ActiveSupport::TimeZone['Central Time (US & Canada)'] # offset -0600
    zone2 = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] # offset -0500
239 240 241 242
    assert zone1 < zone2
    assert zone2 > zone1
    assert zone1 == zone1
  end
243

244 245 246 247 248 249 250
  def test_zone_match
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
    assert zone =~ /Eastern/
    assert zone =~ /New_York/
    assert zone !~ /Nonexistent_Place/
  end

251
  def test_to_s
252
    assert_equal "(GMT+03:00) Moscow", ActiveSupport::TimeZone['Moscow'].to_s
253
  end
254

255
  def test_all_sorted
256
    all = ActiveSupport::TimeZone.all
257 258 259 260
    1.upto( all.length-1 ) do |i|
      assert all[i-1] < all[i]
    end
  end
261

262
  def test_index
263 264 265
    assert_nil ActiveSupport::TimeZone["bogus"]
    assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone["Central Time (US & Canada)"]
    assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone[8]
266
    assert_raise(ArgumentError) { ActiveSupport::TimeZone[false] }
267
  end
268

269
  def test_new
270
    assert_equal ActiveSupport::TimeZone["Central Time (US & Canada)"], ActiveSupport::TimeZone.new("Central Time (US & Canada)")
271
  end
272

273
  def test_us_zones
274 275 276 277
    assert ActiveSupport::TimeZone.us_zones.include?(ActiveSupport::TimeZone["Hawaii"])
    assert !ActiveSupport::TimeZone.us_zones.include?(ActiveSupport::TimeZone["Kuala Lumpur"])
  end

278 279 280 281 282 283
  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')
284
    end
285
end