Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: bb4a1d68f6
Fetching contributors…

Cannot retrieve contributors at this time

file 327 lines (282 sloc) 12.854 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 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 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 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 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 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
require 'abstract_unit'
require 'active_support/time'

class TimeZoneTest < Test::Unit::TestCase
  def test_utc_to_local
    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
  end

  def test_local_to_utc
    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
  end

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

  ActiveSupport::TimeZone::MAPPING.keys.each do |name|
    define_method("test_map_#{name.downcase.gsub(/[^a-z]/, '_')}_to_tzinfo") do
      zone = ActiveSupport::TimeZone[name]
      assert_respond_to zone.tzinfo, :period_for_local
    end
  end

  def test_from_integer_to_map
    assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone[-28800] # PST
  end

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

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

    define_method("test_utc_offset_for_#{name}") do
      period = zone.tzinfo.current_period
      assert_equal period.utc_offset, zone.utc_offset
    end
  end

  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
    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 = ActiveSupport::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
      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?
    end
  end

  def test_unknown_timezones_delegation_to_tzinfo
    zone = ActiveSupport::TimeZone['America/Montevideo']
    assert_equal ActiveSupport::TimeZone, zone.class
    assert_equal zone.object_id, ActiveSupport::TimeZone['America/Montevideo'].object_id
    assert_equal Time.utc(2010, 1, 31, 22), zone.utc_to_local(Time.utc(2010, 2)) # daylight saving offset -0200
    assert_equal Time.utc(2010, 3, 31, 21), zone.utc_to_local(Time.utc(2010, 4)) # standard offset -0300
  end

  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
  end

  def test_local
    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
  end

  def test_local_with_old_date
    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
  end

  def test_local_enforces_spring_dst_rules
    zone = ActiveSupport::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 = ActiveSupport::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

  def test_at
    zone = ActiveSupport::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 = ActiveSupport::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 = ActiveSupport::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_string_with_timezone
    (-11..13).each do |timezone_offset|
      zone = ActiveSupport::TimeZone[timezone_offset]
      twz = zone.parse('1999-12-31 19:00:00')
      assert_equal twz.to_a, zone.parse(twz.to_s).to_a
    end
  end

  def test_parse_with_old_date
    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
  end

  def test_parse_far_future_date_with_time_zone_offset_in_string
    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
  end

  def test_parse_returns_nil_when_string_without_date_information_is_passed_in
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
    assert_nil zone.parse('foobar')
    assert_nil zone.parse(' ')
  end

  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
  end

  def test_parse_should_not_black_out_system_timezone_dst_jump
    zone = ActiveSupport::TimeZone['Pacific Time (US & Canada)']
    zone.stubs(:now).returns(zone.now)
    Time.stubs(:parse).with('2012-03-25 03:29', zone.now).
                       returns(Time.local(0,29,4,25,3,2012,nil,nil,true,"+03:00"))
    twz = zone.parse('2012-03-25 03:29')
    assert_equal [0, 29, 3, 25, 3, 2012], twz.to_a[0,6]
  end

  def test_parse_should_black_out_app_timezone_dst_jump
    zone = ActiveSupport::TimeZone['Pacific Time (US & Canada)']
    zone.stubs(:now).returns(zone.now)
    Time.stubs(:parse).with('2012-03-11 02:29', zone.now).
                       returns(Time.local(0,29,2,11,3,2012,nil,nil,false,"+02:00"))
    twz = zone.parse('2012-03-11 02:29')
    assert_equal [0, 29, 3, 11, 3, 2012], twz.to_a[0,6]
  end

  def test_utc_offset_lazy_loaded_from_tzinfo_when_not_passed_in_to_initialize
    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)
  end

  def test_seconds_to_utc_offset_with_colon
    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)
  end

  def test_seconds_to_utc_offset_without_colon
    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)
  end

  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

  def test_formatted_offset_positive
    zone = ActiveSupport::TimeZone['New Delhi']
    assert_equal "+05:30", zone.formatted_offset
    assert_equal "+0530", zone.formatted_offset(false)
  end

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

  def test_formatted_offset_zero
    zone = ActiveSupport::TimeZone['London']
    assert_equal "+00:00", zone.formatted_offset
    assert_equal "UTC", zone.formatted_offset(true, 'UTC')
  end

  def test_zone_compare
    zone1 = ActiveSupport::TimeZone['Central Time (US & Canada)'] # offset -0600
    zone2 = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] # offset -0500
    assert zone1 < zone2
    assert zone2 > zone1
    assert zone1 == zone1
  end

  def test_zone_match
    zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
    assert zone =~ /Eastern/
    assert zone =~ /New_York/
    assert zone !~ /Nonexistent_Place/
  end

  def test_to_s
    assert_equal "(GMT+05:30) New Delhi", ActiveSupport::TimeZone['New Delhi'].to_s
  end

  def test_all_sorted
    all = ActiveSupport::TimeZone.all
    1.upto( all.length-1 ) do |i|
      assert all[i-1] < all[i]
    end
  end

  def test_index
    assert_nil ActiveSupport::TimeZone["bogus"]
    assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone["Central Time (US & Canada)"]
    assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone[8]
    assert_raise(ArgumentError) { ActiveSupport::TimeZone[false] }
  end

  def test_unknown_zone_should_have_tzinfo_but_exception_on_utc_offset
    zone = ActiveSupport::TimeZone.create("bogus")
    assert_instance_of TZInfo::TimezoneProxy, zone.tzinfo
    assert_raise(TZInfo::InvalidTimezoneIdentifier) { zone.utc_offset }
  end

  def test_unknown_zone_with_utc_offset
    zone = ActiveSupport::TimeZone.create("bogus", -21_600)
    assert_equal(-21_600, zone.utc_offset)
  end

  def test_unknown_zones_dont_store_mapping_keys
    ActiveSupport::TimeZone["bogus"]
    assert !ActiveSupport::TimeZone.zones_map.key?("bogus")
  end

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

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

  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
Something went wrong with that request. Please try again.