所以rails似乎对时区有很好的支持,但我遇到了一个我希望已经解决的需求,我只是在api中没有看到它。
我希望能够根据偏移量找到时区。原因是我连接了一个api,它可以将用户时区作为偏移量返回给我,我不想重新发明轮子,将偏移量变成Rails时区,这样应用程序的其他部分就可以正确使用它。
有什么建议吗?谢谢你的帮助!
您可以在ActiveSupport::TimeZone
上使用[]
方法获取时区。您可以传递时区名称、小时偏移量或秒偏移量。例如:
ActiveSupport::TimeZone["America/Los_Angeles"]
=> (GMT-08:00) America/Los_Angeles
ActiveSupport::TimeZone[-8]
=> (GMT-08:00) America/Los_Angeles
但请记住,偏移量并不等同于时区,因为在任何一天,多个时区都可以在同一偏移量上。
接受答案的问题是,不幸的是,它无法处理两个不同时区具有相同utc偏移的情况。
例如,-7可能指亚利桑那州或丹佛,这是两个不同的时区("美国/菲尼克斯"one_answers"美国/丹佛"),因为亚利桑那州不遵守夏令时。
ActiveSupport::TimeZone[-7]只返回这两个有效时区中的一个。
在稍微简单一点的美国邮政编码数据库中,我需要同样的功能,该数据库包括UTC小时偏移和Y/N字段,指示它是否参与夏令时,因此该数据库中的美国西海岸邮政编码都有"-8"one_answers"Y"。
我找不到一个内置的Rails方法来做这件事,所以我手动创建了一个查找散列,其中的关键字是UTC&DST字段链接,例如"#{utc}#{DST}",其值为时区名称。这种方法也适用于utc偏移,如"5.5"(印度)。
在进行查找的方法中,给定utc和dst值,我指定了一个默认时区(例如美国西海岸),以防哈希查找由于意外值(如"-5N")而返回零(因为东海岸没有任何不应该发生的非dst状态)。
但是,通过创建一个哈希,用夏令时的Y和N值表示所有可能的时区,可以在全局范围内应用相同的方法。
class MyZip
HOUR_DST_TO_TIMEZONE_NAME = {
"-5Y" => "Eastern Time (US & Canada)",
"-6Y" => "Central Time (US & Canada)",
"-7Y" => "Mountain Time (US & Canada)",
"-7N" => "Arizona",
"-8Y" => "Pacific Time (US & Canada)",
"-9Y" => "Alaska",
"-10N" => "Hawaii"
}
def self.timezone_name_from_zip_hour_dst(utc, dst)
key = "#{utc}#{dst}"
return HOUR_DST_TO_TIMEZONE_NAME[key] || MyZip.unknown_timezone_name
end
...
有点破解-但我使用Google的Places API为用户查找位置,这给了我以分钟为单位的UTC偏移量。因此,我只想介绍该位置的相关时区,因为一个UTC偏移量有很多时区。此外,Rails的TimeZone辅助对象不计算夏令时和其他动态偏移。因此,我加入了一个小时的加减法来获得所有相关的时区,而不会让用户不知所措。
Google以分钟为单位返回偏移量,但Rails需要秒。例如,对于加利福尼亚州的一个地点,夏季的偏移量(从API地点)为-420分钟。
offset = -420*60 # convert mins to secs
offset_range = (offset-3600)..(offset+3600)
timezones = ActiveSupport::TimeZone.all.select{|tz| offset_range.include?(tz.utc_offset)}
然后,我在Rails的time_zone_select中将这些时区设置为优先级区域。