Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 8679

Show
Ignore:
Timestamp:
01/21/08 03:55:54 (8 months ago)
Author:
gbuesing
Message:

Replace non-dst-aware TimeZone class with dst-aware class from tzinfo_timezone plugin. TimeZone#adjust and #unadjust are no longer available; tzinfo gem must now be present in order to perform time zone calculations, via #local_to_utc and #utc_to_local methods.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activesupport/CHANGELOG

    r8664 r8679  
    11*SVN* 
     2 
     3* Replace non-dst-aware TimeZone class with dst-aware class from tzinfo_timezone plugin. TimeZone#adjust and #unadjust are no longer available; tzinfo gem must now be present in order to perform time zone calculations, via #local_to_utc and #utc_to_local methods. [Geoff Buesing] 
    24 
    35* Extract ActiveSupport::Callbacks from Active Record, test case setup and teardown, and ActionController::Dispatcher.  #10727 [Josh Peek] 
  • trunk/activesupport/lib/active_support/values/time_zone.rb

    r8635 r8679  
    1 # A value object representing a time zone. A time zone is simply a named 
    2 # offset (in seconds) from GMT. Note that two time zone objects are only 
    3 # equivalent if they have both the same offset, and the same name. 
    4 # 
    5 # A TimeZone instance may be used to convert a Time value to the corresponding 
    6 # time zone. 
    7 # 
    8 # The class also includes #all, which returns a list of all TimeZone objects. 
    91class TimeZone 
     2  MAPPING = { 
     3    "International Date Line West" => "Pacific/Midway", 
     4    "Midway Island"                => "Pacific/Midway", 
     5    "Samoa"                        => "Pacific/Pago_Pago", 
     6    "Hawaii"                       => "Pacific/Honolulu", 
     7    "Alaska"                       => "America/Juneau", 
     8    "Pacific Time (US & Canada)"   => "America/Los_Angeles", 
     9    "Tijuana"                      => "America/Tijuana", 
     10    "Mountain Time (US & Canada)"  => "America/Denver", 
     11    "Arizona"                      => "America/Phoenix", 
     12    "Chihuahua"                    => "America/Chihuahua", 
     13    "Mazatlan"                     => "America/Mazatlan", 
     14    "Central Time (US & Canada)"   => "America/Chicago", 
     15    "Saskatchewan"                 => "America/Regina", 
     16    "Guadalajara"                  => "America/Mexico_City", 
     17    "Mexico City"                  => "America/Mexico_City", 
     18    "Monterrey"                    => "America/Monterrey", 
     19    "Central America"              => "America/Guatemala", 
     20    "Eastern Time (US & Canada)"   => "America/New_York", 
     21    "Indiana (East)"               => "America/Indiana/Indianapolis", 
     22    "Bogota"                       => "America/Bogota", 
     23    "Lima"                         => "America/Lima", 
     24    "Quito"                        => "America/Lima", 
     25    "Atlantic Time (Canada)"       => "America/Halifax", 
     26    "Caracas"                      => "America/Caracas", 
     27    "La Paz"                       => "America/La_Paz", 
     28    "Santiago"                     => "America/Santiago", 
     29    "Newfoundland"                 => "America/St_Johns", 
     30    "Brasilia"                     => "America/Argentina/Buenos_Aires", 
     31    "Buenos Aires"                 => "America/Argentina/Buenos_Aires", 
     32    "Georgetown"                   => "America/Argentina/San_Juan", 
     33    "Greenland"                    => "America/Godthab", 
     34    "Mid-Atlantic"                 => "Atlantic/South_Georgia", 
     35    "Azores"                       => "Atlantic/Azores", 
     36    "Cape Verde Is."               => "Atlantic/Cape_Verde", 
     37    "Dublin"                       => "Europe/Dublin", 
     38    "Edinburgh"                    => "Europe/Dublin", 
     39    "Lisbon"                       => "Europe/Lisbon", 
     40    "London"                       => "Europe/London", 
     41    "Casablanca"                   => "Africa/Casablanca", 
     42    "Monrovia"                     => "Africa/Monrovia", 
     43    "Belgrade"                     => "Europe/Belgrade", 
     44    "Bratislava"                   => "Europe/Bratislava", 
     45    "Budapest"                     => "Europe/Budapest", 
     46    "Ljubljana"                    => "Europe/Ljubljana", 
     47    "Prague"                       => "Europe/Prague", 
     48    "Sarajevo"                     => "Europe/Sarajevo", 
     49    "Skopje"                       => "Europe/Skopje", 
     50    "Warsaw"                       => "Europe/Warsaw", 
     51    "Zagreb"                       => "Europe/Zagreb", 
     52    "Brussels"                     => "Europe/Brussels", 
     53    "Copenhagen"                   => "Europe/Copenhagen", 
     54    "Madrid"                       => "Europe/Madrid", 
     55    "Paris"                        => "Europe/Paris", 
     56    "Amsterdam"                    => "Europe/Amsterdam", 
     57    "Berlin"                       => "Europe/Berlin", 
     58    "Bern"                         => "Europe/Berlin", 
     59    "Rome"                         => "Europe/Rome", 
     60    "Stockholm"                    => "Europe/Stockholm", 
     61    "Vienna"                       => "Europe/Vienna", 
     62    "West Central Africa"          => "Africa/Algiers", 
     63    "Bucharest"                    => "Europe/Bucharest", 
     64    "Cairo"                        => "Africa/Cairo", 
     65    "Helsinki"                     => "Europe/Helsinki", 
     66    "Kyev"                         => "Europe/Kiev", 
     67    "Riga"                         => "Europe/Riga", 
     68    "Sofia"                        => "Europe/Sofia", 
     69    "Tallinn"                      => "Europe/Tallinn", 
     70    "Vilnius"                      => "Europe/Vilnius", 
     71    "Athens"                       => "Europe/Athens", 
     72    "Istanbul"                     => "Europe/Istanbul", 
     73    "Minsk"                        => "Europe/Minsk", 
     74    "Jerusalem"                    => "Asia/Jerusalem", 
     75    "Harare"                       => "Africa/Harare", 
     76    "Pretoria"                     => "Africa/Johannesburg", 
     77    "Moscow"                       => "Europe/Moscow", 
     78    "St. Petersburg"               => "Europe/Moscow", 
     79    "Volgograd"                    => "Europe/Moscow", 
     80    "Kuwait"                       => "Asia/Kuwait", 
     81    "Riyadh"                       => "Asia/Riyadh", 
     82    "Nairobi"                      => "Africa/Nairobi", 
     83    "Baghdad"                      => "Asia/Baghdad", 
     84    "Tehran"                       => "Asia/Tehran", 
     85    "Abu Dhabi"                    => "Asia/Muscat", 
     86    "Muscat"                       => "Asia/Muscat", 
     87    "Baku"                         => "Asia/Baku", 
     88    "Tbilisi"                      => "Asia/Tbilisi", 
     89    "Yerevan"                      => "Asia/Yerevan", 
     90    "Kabul"                        => "Asia/Kabul", 
     91    "Ekaterinburg"                 => "Asia/Yekaterinburg", 
     92    "Islamabad"                    => "Asia/Karachi", 
     93    "Karachi"                      => "Asia/Karachi", 
     94    "Tashkent"                     => "Asia/Tashkent", 
     95    "Chennai"                      => "Asia/Calcutta", 
     96    "Kolkata"                      => "Asia/Calcutta", 
     97    "Mumbai"                       => "Asia/Calcutta", 
     98    "New Delhi"                    => "Asia/Calcutta", 
     99    "Kathmandu"                    => "Asia/Katmandu", 
     100    "Astana"                       => "Asia/Dhaka", 
     101    "Dhaka"                        => "Asia/Dhaka", 
     102    "Sri Jayawardenepura"          => "Asia/Dhaka", 
     103    "Almaty"                       => "Asia/Almaty", 
     104    "Novosibirsk"                  => "Asia/Novosibirsk", 
     105    "Rangoon"                      => "Asia/Rangoon", 
     106    "Bangkok"                      => "Asia/Bangkok", 
     107    "Hanoi"                        => "Asia/Bangkok", 
     108    "Jakarta"                      => "Asia/Jakarta", 
     109    "Krasnoyarsk"                  => "Asia/Krasnoyarsk", 
     110    "Beijing"                      => "Asia/Shanghai", 
     111    "Chongqing"                    => "Asia/Chongqing", 
     112    "Hong Kong"                    => "Asia/Hong_Kong", 
     113    "Urumqi"                       => "Asia/Urumqi", 
     114    "Kuala Lumpur"                 => "Asia/Kuala_Lumpur", 
     115    "Singapore"                    => "Asia/Singapore", 
     116    "Taipei"                       => "Asia/Taipei", 
     117    "Perth"                        => "Australia/Perth", 
     118    "Irkutsk"                      => "Asia/Irkutsk", 
     119    "Ulaan Bataar"                 => "Asia/Ulaanbaatar", 
     120    "Seoul"                        => "Asia/Seoul", 
     121    "Osaka"                        => "Asia/Tokyo", 
     122    "Sapporo"                      => "Asia/Tokyo", 
     123    "Tokyo"                        => "Asia/Tokyo", 
     124    "Yakutsk"                      => "Asia/Yakutsk", 
     125    "Darwin"                       => "Australia/Darwin", 
     126    "Adelaide"                     => "Australia/Adelaide", 
     127    "Canberra"                     => "Australia/Melbourne", 
     128    "Melbourne"                    => "Australia/Melbourne", 
     129    "Sydney"                       => "Australia/Sydney", 
     130    "Brisbane"                     => "Australia/Brisbane", 
     131    "Hobart"                       => "Australia/Hobart", 
     132    "Vladivostok"                  => "Asia/Vladivostok", 
     133    "Guam"                         => "Pacific/Guam", 
     134    "Port Moresby"                 => "Pacific/Port_Moresby", 
     135    "Magadan"                      => "Asia/Magadan", 
     136    "Solomon Is."                  => "Asia/Magadan", 
     137    "New Caledonia"                => "Pacific/Noumea", 
     138    "Fiji"                         => "Pacific/Fiji", 
     139    "Kamchatka"                    => "Asia/Kamchatka", 
     140    "Marshall Is."                 => "Pacific/Majuro", 
     141    "Auckland"                     => "Pacific/Auckland", 
     142    "Wellington"                   => "Pacific/Auckland", 
     143    "Nuku'alofa"                   => "Pacific/Tongatapu" 
     144  } 
     145 
    10146  include Comparable 
    11  
    12147  attr_reader :name, :utc_offset 
    13148 
    14   # Create a new TimeZone object with the given name and offset. The offset is 
    15   # the number of seconds that this time zone is offset from UTC (GMT). Seconds 
    16   # were chosen as the offset unit because that is the unit that Ruby uses 
    17   # to represent time zone offsets (see Time#utc_offset). 
     149  # Create a new TimeZone object with the given name and offset. The 
     150  # offset is the number of seconds that this time zone is offset from UTC 
     151  # (GMT). Seconds were chosen as the offset unit because that is the unit that 
     152  # Ruby uses to represent time zone offsets (see Time#utc_offset). 
    18153  def initialize(name, utc_offset) 
    19154    @name = name 
     
    25160  # string. If +colon+ is false, a colon will not be inserted into the 
    26161  # result. 
    27   def formatted_offset( colon=true ) 
    28     return "" if utc_offset == 0 
     162  def formatted_offset(colon=true) 
     163    utc_offset == 0 ? '' : offset(colon) 
     164  end 
     165   
     166  # Returns the offset of this time zone as a formatted string, of the 
     167  # format "+HH:MM". 
     168  def offset(colon=true) 
    29169    utc_offset.to_utc_offset_s(colon) 
    30   end 
    31  
    32   # Compute and return the current time, in the time zone represented by 
    33   # +self+. 
    34   def now 
    35     adjust(Time.now) 
    36   end 
    37  
    38   # Return the current date in this time zone. 
    39   def today 
    40     now.to_date 
    41   end 
    42  
    43   # Adjust the given time to the time zone represented by +self+. 
    44   def adjust(time) 
    45     time = time.to_time unless time.is_a?(::Time) 
    46     time + utc_offset - time.utc_offset 
    47   end 
    48  
    49   # Reinterprets the given time value as a time in the current time 
    50   # zone, and then adjusts it to return the corresponding time in the 
    51   # local time zone. 
    52   def unadjust(time) 
    53     time = time.to_time unless time.is_a?(::Time) 
    54     time = time.localtime 
    55     time - utc_offset - time.utc_offset 
    56170  end 
    57171 
     
    66180  # Returns a textual representation of this time zone. 
    67181  def to_s 
    68     "(UTC#{formatted_offset}) #{name}" 
     182    "(GMT#{formatted_offset}) #{name}" 
     183  end 
     184 
     185  begin # the following methods depend on the tzinfo gem 
     186    require_library_or_gem "tzinfo" unless Object.const_defined?(:TZInfo) 
     187     
     188    # Compute and return the current time, in the time zone represented by 
     189    # +self+. 
     190    def now 
     191      tzinfo.now 
     192    end 
     193 
     194    # Return the current date in this time zone. 
     195    def today 
     196      now.to_date 
     197    end 
     198 
     199    # Adjust the given time to the time zone represented by +self+. 
     200    def utc_to_local(time) 
     201      tzinfo.utc_to_local(time) 
     202    end 
     203 
     204    def local_to_utc(time, dst=true) 
     205      tzinfo.local_to_utc(time, dst) 
     206    end 
     207 
     208    # Available so that TimeZone instances respond like TZInfo::Timezone instances 
     209    def period_for_local(time, dst=true) 
     210      tzinfo.period_for_local(time, dst) 
     211    end 
     212     
     213    def tzinfo 
     214      return @tzinfo if @tzinfo 
     215      @tzinfo = MAPPING[name] 
     216      if String === @tzinfo 
     217        @tzinfo = TZInfo::Timezone.get(@tzinfo) 
     218        MAPPING[name] = @tzinfo 
     219      end 
     220      @tzinfo 
     221    end 
     222     
     223  rescue LoadError # Tzinfo gem is not available 
     224    # re-raise LoadError only when a tzinfo-dependent method is called: 
     225    %w(now today utc_to_local local_to_utc period_for_local tzinfo).each do |method| 
     226      define_method(method) {|*args| raise LoadError, "TZInfo gem is required for TimeZone##{method}. `gem install tzinfo` and try again."} 
     227    end 
    69228  end 
    70229 
     
    72231 
    73232  class << self 
    74     # Create a new TimeZone instance with the given name and offset. 
    75     def create(name, offset) 
    76       zone = allocate 
    77       zone.send!(:initialize, name, offset) 
    78       zone 
    79     end 
     233    alias_method :create, :new 
    80234 
    81235    # Return a TimeZone instance with the given name, or +nil+ if no 
     
    86240    end 
    87241 
    88     # Return an array of all TimeZone objects. There are multiple TimeZone 
    89     # objects per time zone, in many cases, to make it easier for users to 
    90     # find their own time zone. 
     242    # Return an array of all TimeZone objects. There are multiple 
     243    # TimeZone objects per time zone, in many cases, to make it easier 
     244    # for users to find their own time zone. 
    91245    def all 
    92246      unless @@zones 
    93247        @@zones = [] 
    94         [[-43_200, "International Date Line West" ], 
    95         [-39_600, "Midway Island", "Samoa" ], 
     248        @@zones_map = {} 
     249        [[-39_600, "International Date Line West", "Midway Island", "Samoa" ], 
    96250         [-36_000, "Hawaii" ], 
    97251         [-32_400, "Alaska" ], 
    98252         [-28_800, "Pacific Time (US & Canada)", "Tijuana" ], 
    99          [-25_200, "Mountain Time (US & Canada)", "Chihuahua", "Mazatlan",  
     253         [-25_200, "Mountain Time (US & Canada)", "Chihuahua", "Mazatlan", 
    100254                   "Arizona" ], 
    101255         [-21_600, "Central Time (US & Canada)", "Saskatchewan", "Guadalajara", 
     
    142296         [ 46_800, "Nuku'alofa" ]]. 
    143297        each do |offset, *places| 
    144           places.each { |place| @@zones << create(place, offset).freeze } 
     298          places.each do |place| 
     299            zone = create(place, offset) 
     300            @@zones << zone 
     301            @@zones_map[place] = zone 
     302          end 
    145303        end 
    146304        @@zones.sort! 
     
    157315      case arg 
    158316        when String 
    159           all.find { |z| z.name == arg } 
     317          all # force the zones to be loaded 
     318          @@zones_map[arg] 
    160319        when Numeric 
    161320          arg *= 3600 if arg.abs <= 13 
     
    168327    # A regular expression that matches the names of all time zones in 
    169328    # the USA. 
    170     US_ZONES = /US|Arizona|Indiana|Hawaii|Alaska/ unless defined?(US_ZONES) 
     329    US_ZONES = /US|Arizona|Indiana|Hawaii|Alaska/ 
    171330 
    172331    # A convenience method for returning a collection of TimeZone objects 
  • trunk/activesupport/test/abstract_unit.rb

    r7773 r8679  
    55require 'active_support' 
    66 
     7def uses_gem(gem_name, test_name, version = '> 0') 
     8  require 'rubygems' 
     9  gem gem_name.to_s, version 
     10  require gem_name.to_s 
     11  yield 
     12rescue LoadError 
     13  $stderr.puts "Skipping #{test_name} tests. `gem install #{gem_name}` and try again." 
     14end 
     15 
    716# Wrap tests that use Mocha and skip if unavailable. 
    817unless defined? uses_mocha 
    9   def uses_mocha(test_name) 
    10     require 'rubygems' 
    11     gem 'mocha', '>= 0.5.5' 
    12     require 'mocha' 
    13     yield 
    14   rescue LoadError 
    15     $stderr.puts "Skipping #{test_name} tests. `gem install mocha` and try again." 
     18  def uses_mocha(test_name, &block) 
     19    uses_gem('mocha', test_name, '>= 0.5.5', &block) 
     20  end 
     21end 
     22 
     23# Wrap tests that use TZInfo and skip if unavailable. 
     24unless defined? uses_tzinfo 
     25  def uses_tzinfo(test_name, &block) 
     26    uses_gem('tzinfo', test_name, &block) 
    1627  end 
    1728end 
  • trunk/activesupport/test/time_zone_test.rb

    r8563 r8679  
    22 
    33class TimeZoneTest < Test::Unit::TestCase 
    4   class MockTime 
    5     def self.now 
    6       Time.utc( 2004, 7, 25, 14, 49, 00 ) 
     4   
     5  uses_tzinfo 'TestTimeZoneCalculations' do 
     6     
     7    def test_utc_to_local 
     8      silence_warnings do # silence warnings raised by tzinfo gem 
     9        zone = TimeZone['Eastern Time (US & Canada)'] 
     10        assert_equal Time.utc(1999, 12, 31, 19), zone.utc_to_local(Time.utc(2000, 1)) # standard offset -0500 
     11        assert_equal Time.utc(2000, 6, 30, 20), zone.utc_to_local(Time.utc(2000, 7)) # dst offset -0400 
     12      end 
     13    end 
     14   
     15    def test_local_to_utc 
     16      silence_warnings do # silence warnings raised by tzinfo gem 
     17        zone = TimeZone['Eastern Time (US & Canada)'] 
     18        assert_equal Time.utc(2000, 1, 1, 5), zone.local_to_utc(Time.utc(2000, 1)) # standard offset -0500 
     19        assert_equal Time.utc(2000, 7, 1, 4), zone.local_to_utc(Time.utc(2000, 7)) # dst offset -0400 
     20      end 
     21    end 
     22     
     23    def test_period_for_local 
     24      silence_warnings do # silence warnings raised by tzinfo gem 
     25        zone = TimeZone['Eastern Time (US & Canada)'] 
     26        assert_instance_of TZInfo::TimezonePeriod, zone.period_for_local(Time.utc(2000)) 
     27      end 
     28    end 
     29     
     30    TimeZone::MAPPING.keys.each do |name| 
     31      define_method("test_map_#{name.downcase.gsub(/[^a-z]/, '_')}_to_tzinfo") do 
     32        silence_warnings do # silence warnings raised by tzinfo gem 
     33          zone = TimeZone[name] 
     34          assert zone.tzinfo.respond_to?(:period_for_local) 
     35        end 
     36      end 
    737    end 
    838 
    9     def self.local(*args) 
    10       Time.utc(*args) 
     39    TimeZone.all.each do |zone| 
     40      name = zone.name.downcase.gsub(/[^a-z]/, '_') 
     41      define_method("test_from_#{name}_to_map") do 
     42        silence_warnings do # silence warnings raised by tzinfo gem 
     43          assert_instance_of TimeZone, TimeZone[zone.name] 
     44        end 
     45      end 
     46 
     47      define_method("test_utc_offset_for_#{name}") do 
     48        silence_warnings do # silence warnings raised by tzinfo gem 
     49          period = zone.tzinfo.period_for_utc(Time.utc(2006,1,1,0,0,0)) 
     50          assert_equal period.utc_offset, zone.utc_offset 
     51        end 
     52      end 
     53    end 
     54 
     55    uses_mocha 'TestTimeZoneNowAndToday' do 
     56      def test_now 
     57        TZInfo::DataTimezone.any_instance.stubs(:now).returns(Time.utc(2000)) 
     58        assert_equal Time.utc(2000), TimeZone['Eastern Time (US & Canada)'].now 
     59      end 
     60     
     61      def test_today 
     62        TZInfo::DataTimezone.any_instance.stubs(:now).returns(Time.utc(2000)) 
     63        assert_equal Date.new(2000), TimeZone['Eastern Time (US & Canada)'].today 
     64      end 
    1165    end 
    1266  end 
    13  
    14   TimeZone::Time = MockTime 
    15  
     67   
    1668  def test_formatted_offset_positive 
    17     zone = TimeZone.create( "Test", 4200 ) 
    18     assert_equal "+01:10", zone.formatted_offset 
     69    zone = TimeZone['Moscow'] 
     70    assert_equal "+03:00", zone.formatted_offset 
     71    assert_equal "+0300", zone.formatted_offset(false) 
    1972  end 
    20  
     73   
    2174  def test_formatted_offset_negative 
    22     zone = TimeZone.create( "Test", -4200 ) 
    23     assert_equal "-01:10", zone.formatted_offset 
     75    zone = TimeZone['Eastern Time (US & Canada)'] 
     76    assert_equal "-05:00", zone.formatted_offset 
     77    assert_equal "-0500", zone.formatted_offset(false) 
    2478  end 
    25  
    26   def test_now 
    27     zone = TimeZone.create( "Test", 4200 ) 
    28     assert_equal Time.local(2004,7,25,15,59,00).to_a[0,6], zone.now.to_a[0,6] 
    29   end 
    30  
    31   def test_today 
    32     zone = TimeZone.create( "Test", 43200 ) 
    33     assert_equal Date.new(2004,7,26), zone.today 
    34   end 
    35  
    36   def test_adjust_negative 
    37     zone = TimeZone.create( "Test", -4200 ) # 4200s == 70 mins 
    38     assert_equal Time.utc(2004,7,24,23,55,0), zone.adjust(Time.utc(2004,7,25,1,5,0)) 
    39   end 
    40  
    41   def test_adjust_positive 
    42     zone = TimeZone.create( "Test", 4200 ) 
    43     assert_equal Time.utc(2004,7,26,1,5,0), zone.adjust(Time.utc(2004,7,25,23,55,0)) 
    44   end 
    45  
    46   def test_unadjust 
    47     zone = TimeZone.create( "Test", 4200 ) 
    48     expect = Time.utc(2004,7,24,23,55,0).to_a[0,6] 
    49     actual = zone.unadjust(Time.utc(2004,7,25,1,5,0)).to_a[0,6] 
    50     assert_equal expect, actual 
    51   end 
    52  
     79   
    5380  def test_zone_compare 
    54     zone1 = TimeZone.create( "Test1", 4200 ) 
    55     zone2 = TimeZone.create( "Test1", 5600 ) 
     81    zone1 = TimeZone['Central Time (US & Canada)'] # offset -0600 
     82    zone2 = TimeZone['Eastern Time (US & Canada)'] # offset -0500 
    5683    assert zone1 < zone2 
    5784    assert zone2 > zone1 
    58  
    59     zone1 = TimeZone.create( "Able", 10000 ) 
    60     zone2 = TimeZone.create( "Zone", 10000 ) 
    61     assert zone1 < zone2 
    62     assert zone2 > zone1 
    63  
    64     zone1 = TimeZone.create( "Able", 10000 ) 
    6585    assert zone1 == zone1 
    6686  end 
    67  
     87   
    6888  def test_to_s 
    69     zone = TimeZone.create( "Test", 4200 ) 
    70     assert_equal "(UTC+01:10) Test", zone.to_s 
     89    assert_equal "(GMT+03:00) Moscow", TimeZone['Moscow'].to_s 
    7190  end 
    72  
     91   
    7392  def test_all_sorted 
    7493    all = TimeZone.all 
     
    7796    end 
    7897  end 
    79  
     98   
    8099  def test_index 
    81100    assert_nil TimeZone["bogus"] 
    82     assert_not_nil TimeZone["Central Time (US & Canada)"] 
    83     assert_not_nil TimeZone[8] 
     101    assert_instance_of TimeZone, TimeZone["Central Time (US & Canada)"] 
     102    assert_instance_of TimeZone, TimeZone[8] 
    84103    assert_raises(ArgumentError) { TimeZone[false] } 
    85104  end 
    86105   
    87106  def test_new 
    88     a = TimeZone.new("Berlin") 
    89     b = TimeZone.new("Berlin") 
    90     assert_same a, b 
    91     assert_nil TimeZone.new("bogus") 
     107    assert_equal TimeZone["Central Time (US & Canada)"], TimeZone.new("Central Time (US & Canada)") 
    92108  end 
    93109   
     
    97113  end  
    98114end 
     115