diff options
author | Jeremy Daer <jeremydaer@gmail.com> | 2016-04-19 22:03:29 -0700 |
---|---|---|
committer | Jeremy Daer <jeremydaer@gmail.com> | 2016-04-19 22:59:21 -0700 |
commit | a0dcc95cd80c5546579fdc50294fdfefc289f41b (patch) | |
tree | a40c2e754a51451cd025299c2c16a8195863582d | |
parent | ff82d7001fb9a4239d9a52d6af4f6d5bb056cc23 (diff) | |
parent | 318ee5413038fc33b302fcb4f41c146c8f10315f (diff) | |
download | rails-a0dcc95cd80c5546579fdc50294fdfefc289f41b.tar.gz rails-a0dcc95cd80c5546579fdc50294fdfefc289f41b.tar.bz2 rails-a0dcc95cd80c5546579fdc50294fdfefc289f41b.zip |
Merge pull request #20625 from Envek/add_country_zones_method
Add ActiveSupport::TimeZone.country_zones helper
-rw-r--r-- | actionview/lib/action_view/helpers/form_options_helper.rb | 9 | ||||
-rw-r--r-- | activesupport/CHANGELOG.md | 11 | ||||
-rw-r--r-- | activesupport/lib/active_support/values/time_zone.rb | 14 | ||||
-rw-r--r-- | activesupport/test/time_zone_test.rb | 5 | ||||
-rw-r--r-- | railties/lib/rails/tasks/misc.rake | 29 |
5 files changed, 57 insertions, 11 deletions
diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index 430051379d..b277efd7b6 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -268,10 +268,11 @@ module ActionView # for more information.) # # You can also supply an array of ActiveSupport::TimeZone objects - # as +priority_zones+, so that they will be listed above the rest of the - # (long) list. (You can use ActiveSupport::TimeZone.us_zones as a convenience - # for obtaining a list of the US time zones, or a Regexp to select the zones - # of your choice) + # as +priority_zones+ so that they will be listed above the rest of the + # (long) list. You can use ActiveSupport::TimeZone.us_zones for a list + # of US time zones, ActiveSupport::TimeZone.country_zones(country_code) + # for another country's time zones, or a Regexp to select the zones of + # your choice. # # Finally, this method supports a <tt>:default</tt> option, which selects # a default ActiveSupport::TimeZone if the object's time zone is +nil+. diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 21dd0657aa..f8423c3ef8 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,14 @@ +* `ActiveSupport::TimeZone.country_zones(country_code)` looks up the + country's time zones by its two-letter ISO3166 country code, e.g. + + >> ActiveSupport::TimeZone.country_zones(:jp).map(&:to_s) + => ["(GMT+09:00) Osaka"] + + >> ActiveSupport::TimeZone.country_zones(:uy).map(&:to_s) + => ["(GMT-03:00) Montevideo"] + + *Andrey Novikov* + * `Array#sum` compat with Ruby 2.4's native method. Ruby 2.4 introduces `Array#sum`, but it only supports numeric elements, diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 118bf8eab0..00fdb22c31 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -184,6 +184,7 @@ module ActiveSupport UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(':', '') @lazy_zones_map = Concurrent::Map.new + @country_zones = Concurrent::Map.new class << self # Assumes self represents an offset from UTC in seconds (as returned from @@ -242,7 +243,18 @@ module ActiveSupport # A convenience method for returning a collection of TimeZone objects # for time zones in the USA. def us_zones - @us_zones ||= all.find_all { |z| z.name =~ /US|Arizona|Indiana|Hawaii|Alaska/ } + country_zones(:us) + end + + # A convenience method for returning a collection of TimeZone objects + # for time zones in the country specified by its ISO 3166-1 Alpha2 code. + def country_zones(country_code) + code = country_code.to_s.upcase + @country_zones[code] ||= + TZInfo::Country.get(code).zone_identifiers.map do |tz_id| + name = MAPPING.key(tz_id) + name && self[name] + end.compact.sort! end private diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 00d40c4497..d0674eb03a 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -491,6 +491,11 @@ class TimeZoneTest < ActiveSupport::TestCase assert !ActiveSupport::TimeZone.us_zones.include?(ActiveSupport::TimeZone["Kuala Lumpur"]) end + def test_country_zones + assert ActiveSupport::TimeZone.country_zones("ru").include?(ActiveSupport::TimeZone["Moscow"]) + assert !ActiveSupport::TimeZone.country_zones(:ru).include?(ActiveSupport::TimeZone["Kuala Lumpur"]) + end + def test_to_yaml assert_equal("--- !ruby/object:ActiveSupport::TimeZone\nname: Pacific/Honolulu\n", ActiveSupport::TimeZone["Hawaii"].to_yaml) assert_equal("--- !ruby/object:ActiveSupport::TimeZone\nname: Europe/London\n", ActiveSupport::TimeZone["Europe/London"].to_yaml) diff --git a/railties/lib/rails/tasks/misc.rake b/railties/lib/rails/tasks/misc.rake index 4195106961..371bcb8fe0 100644 --- a/railties/lib/rails/tasks/misc.rake +++ b/railties/lib/rails/tasks/misc.rake @@ -10,29 +10,46 @@ task about: :environment do end namespace :time do + desc 'List all time zones, list by two-letter country code (`rake time:zones[US]`), or list by UTC offset (`rake time:zones[-8]`)' + task :zones, :country_or_offset do |t, args| + zones, offset = ActiveSupport::TimeZone.all, nil + + if country_or_offset = args[:country_or_offset] + begin + zones = ActiveSupport::TimeZone.country_zones(country_or_offset) + rescue TZInfo::InvalidCountryCode + offset = country_or_offset + end + end + + build_time_zone_list zones, offset + end + namespace :zones do - desc 'Displays all time zones, also available: time:zones:us, time:zones:local -- filter with OFFSET parameter, e.g., OFFSET=-6' + # desc 'Displays all time zones, also available: time:zones:us, time:zones:local -- filter with OFFSET parameter, e.g., OFFSET=-6' task :all do - build_time_zone_list(:all) + build_time_zone_list ActiveSupport::TimeZone.all end # desc 'Displays names of US time zones recognized by the Rails TimeZone class, grouped by offset. Results can be filtered with optional OFFSET parameter, e.g., OFFSET=-6' task :us do - build_time_zone_list(:us_zones) + build_time_zone_list ActiveSupport::TimeZone.us_zones end # desc 'Displays names of time zones recognized by the Rails TimeZone class with the same offset as the system local time' task :local do require 'active_support' require 'active_support/time' + jan_offset = Time.now.beginning_of_year.utc_offset jul_offset = Time.now.beginning_of_year.change(month: 7).utc_offset offset = jan_offset < jul_offset ? jan_offset : jul_offset - build_time_zone_list(:all, offset) + + build_time_zone_list(ActiveSupport::TimeZone.all, offset) end # to find UTC -06:00 zones, OFFSET can be set to either -6, -6:00 or 21600 - def build_time_zone_list(method, offset = ENV['OFFSET']) + def build_time_zone_list(zones, offset = ENV['OFFSET']) require 'active_support' require 'active_support/time' if offset @@ -47,7 +64,7 @@ namespace :time do end end previous_offset = nil - ActiveSupport::TimeZone.__send__(method).each do |zone| + zones.each do |zone| if offset.nil? || offset == zone.utc_offset puts "\n* UTC #{zone.formatted_offset} *" unless zone.utc_offset == previous_offset puts zone.name |