From 0285d648616682453e5ad4a23a4c6efc361f575d Mon Sep 17 00:00:00 2001 From: Ryan McGeary Date: Sun, 2 Aug 2009 17:49:20 -0400 Subject: [PATCH] Return the most popular TimeZone given a UTC offset * For the most part, the popular zone is based on population * E.g. ActiveSupport::TimeZone[-5] now returns 'Eastern Time (US & Canada)' instead of 'Bogota' --- .../lib/active_support/values/time_zone.rb | 46 +++++++++++--------- activesupport/test/time_zone_test.rb | 37 ++++++++++++++++ 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 564528b..8717732 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -313,6 +313,9 @@ module ActiveSupport unless const_defined?(:ZONES) ZONES = [] ZONES_MAP = {} + OFFSETS_MAP = {} + # The first place for each offset is the most popular default; most + # defaults are based on population. [[-39_600, "International Date Line West", "Midway Island", "Samoa" ], [-36_000, "Hawaii" ], [-32_400, "Alaska" ], @@ -326,39 +329,37 @@ module ActiveSupport [-16_200, "Caracas" ], [-14_400, "Atlantic Time (Canada)", "La Paz", "Santiago" ], [-12_600, "Newfoundland" ], - [-10_800, "Brasilia", "Buenos Aires", "Georgetown", "Greenland" ], + [-10_800, "Buenos Aires", "Brasilia", "Georgetown", "Greenland" ], [ -7_200, "Mid-Atlantic" ], - [ -3_600, "Azores", "Cape Verde Is." ], - [ 0, "Dublin", "Edinburgh", "Lisbon", "London", "Casablanca", - "Monrovia", "UTC" ], - [ 3_600, "Belgrade", "Bratislava", "Budapest", "Ljubljana", "Prague", - "Sarajevo", "Skopje", "Warsaw", "Zagreb", "Brussels", - "Copenhagen", "Madrid", "Paris", "Amsterdam", "Berlin", - "Bern", "Rome", "Stockholm", "Vienna", - "West Central Africa" ], - [ 7_200, "Bucharest", "Cairo", "Helsinki", "Kyiv", "Riga", "Sofia", - "Tallinn", "Vilnius", "Athens", "Istanbul", "Minsk", + [ -3_600, "Cape Verde Is.", "Azores" ], + [ 0, "UTC", "London", "Dublin", "Edinburgh", "Lisbon", + "Casablanca", "Monrovia" ], + [ 3_600, "Berlin", "Belgrade", "Bratislava", "Budapest", "Ljubljana", + "Prague", "Sarajevo", "Skopje", "Warsaw", "Zagreb", + "Brussels", "Copenhagen", "Madrid", "Paris", "Amsterdam", + "Bern", "Rome", "Stockholm", "Vienna", "West Central Africa" ], + [ 7_200, "Istanbul", "Bucharest", "Cairo", "Helsinki", "Kyiv", "Riga", + "Sofia", "Tallinn", "Vilnius", "Athens", "Minsk", "Jerusalem", "Harare", "Pretoria" ], [ 10_800, "Moscow", "St. Petersburg", "Volgograd", "Kuwait", "Riyadh", "Nairobi", "Baghdad" ], [ 12_600, "Tehran" ], - [ 14_400, "Abu Dhabi", "Muscat", "Baku", "Tbilisi", "Yerevan" ], + [ 14_400, "Baku", "Abu Dhabi", "Muscat", "Tbilisi", "Yerevan" ], [ 16_200, "Kabul" ], - [ 18_000, "Ekaterinburg", "Islamabad", "Karachi", "Tashkent" ], - [ 19_800, "Chennai", "Kolkata", "Mumbai", "New Delhi", "Sri Jayawardenepura" ], + [ 18_000, "Karachi", "Ekaterinburg", "Islamabad", "Tashkent" ], + [ 19_800, "Mumbai", "Chennai", "Kolkata", "New Delhi", "Sri Jayawardenepura" ], [ 20_700, "Kathmandu" ], - [ 21_600, "Astana", "Dhaka", "Almaty", - "Novosibirsk" ], + [ 21_600, "Dhaka", "Astana", "Almaty", "Novosibirsk" ], [ 23_400, "Rangoon" ], - [ 25_200, "Bangkok", "Hanoi", "Jakarta", "Krasnoyarsk" ], + [ 25_200, "Jakarta", "Bangkok", "Hanoi", "Krasnoyarsk" ], [ 28_800, "Beijing", "Chongqing", "Hong Kong", "Urumqi", "Kuala Lumpur", "Singapore", "Taipei", "Perth", "Irkutsk", "Ulaan Bataar" ], [ 32_400, "Seoul", "Osaka", "Sapporo", "Tokyo", "Yakutsk" ], - [ 34_200, "Darwin", "Adelaide" ], - [ 36_000, "Canberra", "Melbourne", "Sydney", "Brisbane", "Hobart", + [ 34_200, "Adelaide", "Darwin" ], + [ 36_000, "Sydney", "Canberra", "Melbourne", "Brisbane", "Hobart", "Vladivostok", "Guam", "Port Moresby" ], - [ 39_600, "Magadan", "Solomon Is.", "New Caledonia" ], + [ 39_600, "New Caledonia", "Magadan", "Solomon Is." ], [ 43_200, "Fiji", "Kamchatka", "Marshall Is.", "Auckland", "Wellington" ], [ 46_800, "Nuku'alofa" ]]. @@ -369,9 +370,11 @@ module ActiveSupport ZONES << zone ZONES_MAP[place] = zone end + OFFSETS_MAP[offset] = places end ZONES.freeze ZONES_MAP.freeze + OFFSETS_MAP.freeze US_ZONES = ZONES.find_all { |z| z.name =~ /US|Arizona|Indiana|Hawaii|Alaska/ } US_ZONES.freeze @@ -405,7 +408,8 @@ module ActiveSupport ZONES_MAP[arg] when Numeric, ActiveSupport::Duration arg *= 3600 if arg.abs <= 13 - all.find { |z| z.utc_offset == arg.to_i } + places = OFFSETS_MAP[arg.to_i] || [] + ZONES_MAP[places.first] else raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}" end diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 99c4310..9d5a832 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -46,6 +46,42 @@ class TimeZoneTest < Test::Unit::TestCase end end + def test_popular_default_zone_for_each_offset + assert_equal "International Date Line West", ActiveSupport::TimeZone[-39_600].name + assert_equal "Hawaii", ActiveSupport::TimeZone[-36_000].name + assert_equal "Alaska", ActiveSupport::TimeZone[-32_400].name + assert_equal "Pacific Time (US & Canada)", ActiveSupport::TimeZone[-28_800].name + assert_equal "Mountain Time (US & Canada)", ActiveSupport::TimeZone[-25_200].name + assert_equal "Central Time (US & Canada)", ActiveSupport::TimeZone[-21_600].name + assert_equal "Eastern Time (US & Canada)", ActiveSupport::TimeZone[-18_000].name + assert_equal "Caracas", ActiveSupport::TimeZone[-16_200].name + assert_equal "Atlantic Time (Canada)", ActiveSupport::TimeZone[-14_400].name + assert_equal "Newfoundland", ActiveSupport::TimeZone[-12_600].name + assert_equal "Buenos Aires", ActiveSupport::TimeZone[-10_800].name + assert_equal "Mid-Atlantic", ActiveSupport::TimeZone[ -7_200].name + assert_equal "Cape Verde Is.", ActiveSupport::TimeZone[ -3_600].name + assert_equal "UTC", ActiveSupport::TimeZone[ 0].name + assert_equal "Berlin", ActiveSupport::TimeZone[ 3_600].name + assert_equal "Istanbul", ActiveSupport::TimeZone[ 7_200].name + assert_equal "Moscow", ActiveSupport::TimeZone[ 10_800].name + assert_equal "Tehran", ActiveSupport::TimeZone[ 12_600].name + assert_equal "Baku", ActiveSupport::TimeZone[ 14_400].name + assert_equal "Kabul", ActiveSupport::TimeZone[ 16_200].name + assert_equal "Karachi", ActiveSupport::TimeZone[ 18_000].name + assert_equal "Mumbai", ActiveSupport::TimeZone[ 19_800].name + assert_equal "Kathmandu", ActiveSupport::TimeZone[ 20_700].name + assert_equal "Dhaka", ActiveSupport::TimeZone[ 21_600].name + assert_equal "Rangoon", ActiveSupport::TimeZone[ 23_400].name + assert_equal "Jakarta", ActiveSupport::TimeZone[ 25_200].name + assert_equal "Beijing", ActiveSupport::TimeZone[ 28_800].name + assert_equal "Seoul", ActiveSupport::TimeZone[ 32_400].name + assert_equal "Adelaide", ActiveSupport::TimeZone[ 34_200].name + assert_equal "Sydney", ActiveSupport::TimeZone[ 36_000].name + assert_equal "New Caledonia", ActiveSupport::TimeZone[ 39_600].name + assert_equal "Fiji", ActiveSupport::TimeZone[ 43_200].name + assert_equal "Nuku'alofa", ActiveSupport::TimeZone[ 46_800].name + end + def test_now with_env_tz 'US/Eastern' do Time.stubs(:now).returns(Time.local(2000)) @@ -255,6 +291,7 @@ class TimeZoneTest < Test::Unit::TestCase def test_index assert_nil ActiveSupport::TimeZone["bogus"] + assert_nil ActiveSupport::TimeZone[25] # bogus offset 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] } -- 1.6.3.3