TZInfo 和 ActiveSupport 不支持通过缩写查找时区。那些可用的缩写实际上是Time Zone DatabaseTZInfo::Timezone.get
中旧时区的标识符。
不过,您可以使用 TZInfo 构建自己的从缩写到时区标识符的映射。例如:
# Consider abbreviations used in the current year.
from = Time.utc(Time.now.utc.year)
to = Time.utc(from.year + 1)
# Build an array of [abbreviation, identifier] pairs.
abbrev_identifiers = TZInfo::Timezone.all_data_zones.flat_map do |tz|
abbrevs = tz.offsets_up_to(to, from).map {|o| o.abbreviation.to_s }.uniq
abbrevs.map {|a| [a, tz.identifier] }
end
# Create a Hash using abbreviation as the key and an array of identifiers as the value.
lookup = abbrev_identifiers.each.with_object(Hash.new {|h,k| h[k] = [] }) {|(a, i), h| h[a] << i }
您现在可以使用lookup
来获取时区标识符(适合与 一起使用TZInfo::Timezone.get
)。以 MST 为例:
p lookup['MST']
#=> ["America/Boise", "America/Cambridge_Bay", "America/Chihuahua", "America/Creston", "America/Dawson", "America/Dawson_Creek", "America/Denver", "America/Edmonton", "America/Fort_Nelson", "America/Hermosillo", "America/Inuvik", "America/Mazatlan", "America/Ojinaga", "America/Phoenix", "America/Whitehorse", "America/Yellowknife", "MST", "MST7MDT"]
自 1970 年以来,这些时区中的每一个都将在某个时候使用不同的规则(至少在过去几年中发布时区数据库)。如果您只对在较小窗口内处理时间感兴趣,那么您可以将查找过滤到仅在该窗口内具有不同规则的时区:
current_year = lookup.map.with_object(Hash.new) do |(a, z), h|
h[a] = z.uniq {|i| TZInfo::Timezone.get(i).transitions_up_to(to, from) }
end
p current_year['MST']
#=> ["America/Boise", "America/Chihuahua", "America/Creston", "America/Dawson"]
根据您的应用程序,您可能需要预先计算和存储查找。遍历时区将在进程的生命周期内将每个时区加载到内存中。
请注意,时区数据库中使用并由 TZInfo 返回的缩写与您链接到的时区缩写列表Wikipedia 页面上的缩写不同。在很多情况下,没有标准的缩写,时区数据库和维基百科的作者将使用不同的来源和方法。