From 2d95956e8b564236f0c5f98ea18d8535b05344f0 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Mon, 19 Feb 2018 10:24:13 +0000 Subject: [PATCH] Return all mappings for a timezone id in `country_zones` Some timezones like `Europe/London` have multiple mappings in `ActiveSupport::TimeZone::MAPPING` so return all of them instead of the first one found by using `Hash#value`. e.g: # Before ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh"] # After ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh", "London"] Fixes #31668. --- activesupport/CHANGELOG.md | 16 ++++++++++++++++ .../lib/active_support/values/time_zone.rb | 7 +++++-- activesupport/test/time_zone_test.rb | 10 ++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 66b7365916..73896be453 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,21 @@ ## Rails 6.0.0.alpha (Unreleased) ## +* Return all mappings for a timezone identifier in `country_zones` + + Some timezones like `Europe/London` have multiple mappings in + `ActiveSupport::TimeZone::MAPPING` so return all of them instead + of the first one found by using `Hash#value`. e.g: + + # Before + ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh"] + + # After + ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh", "London"] + + Fixes #31668. + + *Andrew White* + * `String#truncate_bytes` to truncate a string to a maximum bytesize without breaking multibyte characters or grapheme clusters like 👩‍👩‍👦‍👦. diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 1de4748a46..9dfaddb825 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -267,11 +267,14 @@ module ActiveSupport country = TZInfo::Country.get(code) country.zone_identifiers.map do |tz_id| if MAPPING.value?(tz_id) - self[MAPPING.key(tz_id)] + MAPPING.inject([]) do |memo, (key, value)| + memo << self[key] if value == tz_id + memo + end else create(tz_id, nil, TZInfo::Timezone.new(tz_id)) end - end.sort! + end.flatten(1).sort! end def zones_map diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 405c8f315b..63ca22efb5 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -756,6 +756,16 @@ class TimeZoneTest < ActiveSupport::TestCase assert_not_includes ActiveSupport::TimeZone.country_zones(:ru), ActiveSupport::TimeZone["Kuala Lumpur"] end + def test_country_zones_with_and_without_mappings + assert_includes ActiveSupport::TimeZone.country_zones("au"), ActiveSupport::TimeZone["Adelaide"] + assert_includes ActiveSupport::TimeZone.country_zones("au"), ActiveSupport::TimeZone["Australia/Lord_Howe"] + end + + def test_country_zones_with_multiple_mappings + assert_includes ActiveSupport::TimeZone.country_zones("gb"), ActiveSupport::TimeZone["Edinburgh"] + assert_includes ActiveSupport::TimeZone.country_zones("gb"), ActiveSupport::TimeZone["London"] + end + def test_country_zones_without_mappings assert_includes ActiveSupport::TimeZone.country_zones(:sv), ActiveSupport::TimeZone["America/El_Salvador"] end