rails: Inconsistent output from ActiveSupport::TimeZone.all

Due to caching, ActiveSupport::TimeZone.all returns different results if a non-ActiveSupport-supported zone was looked up first.

ActiveSupport::TimeZone.all
# not in ActiveSupport::TimeZone::MAPPING, but still a valid zone
chicago = ActiveSupport::TimeZone['America/Chicago']
ActiveSupport::TimeZone.all.include?(chicago)
=> false
chicago = ActiveSupport::TimeZone['America/Chicago']
ActiveSupport::TimeZone.all.include?(chicago)
=> true

This affects time_zone_options_for_select, in that the selected arg of that function is a string matched to the names of zones in ActiveSupport::TimeZone.all. If your app stores timezones in TZInfo format, the helper may not generate an option tag for a recognized zone.

I see two ways around this:

  1. Change the helper to recognize TZInfo identifiers
  2. Update the zones cache when lazy-loading time zones.

Changing the helper might unintentionally change your data (“America/Chicago” would get converted to “Central Time”). It seems like Rails is opinionated about what zones it wants to use, so that might not be a big deal. The second approach avoids that problem, but still requires you to look up the alternate zone before it shows up in the list.

Thoughts?

About this issue

  • Original URL
  • State: closed
  • Created 12 years ago
  • Comments: 19 (14 by maintainers)

Commits related to this issue

Most upvoted comments

Fixed by #31176.

AS::TimeZone.all changing depending on what happens to have been looked up is even stranger, asking for brittle, hard to reproduce bugs.

How about ensuring that it always faithfully returns the collection of time zones in MAPPING?

def all
  @all ||= MAPPING.transform_values { |tz_identifier| find_tzinfo tz_identifier }
end