【问题标题】:Rails timezone from offsetRails 时区偏移量
【发布时间】:2011-09-02 18:59:04
【问题描述】:

所以看起来 rails 对时区有很好的支持,但我遇到了一个我希望已经解决的要求,我只是在 api 中没有看到它。

我希望能够根据偏移量找到 TimeZone。原因是我连接到一个 api,它将用户时区作为偏移量返回给我,并且不想重新发明轮子,将偏移量转换为 Rails TimeZone,以便应用程序的其余部分可以正确使用它。

有什么建议吗?感谢您的帮助!

【问题讨论】:

  • +1 好问题。然而,另一个需要考虑的因素是像亚利桑那州这样没有遵循夏令时的情况。要找到合适的美国区域,您不仅需要考虑偏移量,还需要考虑是否实施 DST。这在美国以外会更加复杂。

标签: ruby-on-rails timezone


【解决方案1】:

您可以使用ActiveSupport::TimeZone 上的[] 方法获取时区。您可以传递时区名称、小时偏移量或秒偏移量。例如:

ActiveSupport::TimeZone["America/Los_Angeles"]                              
 => (GMT-08:00) America/Los_Angeles
ActiveSupport::TimeZone[-8]                              
 => (GMT-08:00) America/Los_Angeles

但请记住,偏移量并不等同于时区,因为多个时区在任何一天都可以位于相同的偏移量上。

【讨论】:

  • 太棒了!正是我想要的。一位同事也提醒我,偏移量不会一对一地映射到时区,因为我知道我 99.9% 的用户是美国用户,我认为从偏移量中做出有根据的猜测是值得的。谢谢!
  • 谢谢!将此与时区结合使用时刻:stackoverflow.com/questions/30756405/…
  • 这在某些情况下是错误的,无法弄清楚为什么,例如Time.zone = ActiveSupport::TimeZone[-4] 然后Time.zone.now 返回偏移量-3 :(。有什么帮助吗?
  • Time.zone = 'Etc/GMT+8'一起工作
【解决方案2】:

已接受答案的问题在于,遗憾的是它无法处理两个不同时区具有相同 UTC 偏移量的情况。

例如,-7 可能指的是亚利桑那州或丹佛,它们是两个不同的时区(“美国/凤凰城”和“美国/丹佛”),因为亚利桑那州不遵守夏令时。

ActiveSupport::TimeZone[-7] 仅返回这两个有效时区之一。

在美国邮政编码数据库的稍微简单的情况下,我需要相同的功能,其中包括 UTC 小时偏移量和指示它是否参与夏令时的 Y/N 字段,因此该数据库中的美国西海岸邮政编码都具有“ -8”和“Y”。

我找不到内置的 Rails 方法来执行此操作,因此我手动创建了一个查找哈希,其中键是 UTC 和 DST 字段连接,例如“#{utc}#{dst}”和值是时区名称。此方法也适用于“5.5”(印度)等 UTC 偏移量。

在进行查找的方法中给出了 utc 和 dst 值,我指定了一个默认时区(例如美国西海岸),以防哈希查找返回 nil,因为诸如“-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
...

【讨论】:

    【解决方案3】:

    有点小技巧 - 但我使用 Google 的 Places API 来查找用户的位置,这给了我以分钟为单位的 UTC 偏移量。因此,我只想显示该位置的相关时区,因为一个 UTC 偏移量有很多。此外,Rails 的 TimeZone 助手不计算夏令时和其他动态偏移。因此,我加入了加减一小时的时间来获取所有相关时区,但希望不会让用户不知所措。

    Google 以分钟为单位返回偏移量,但 Rails 需要秒。例如,对于加利福尼亚州的某个位置,夏季的偏移量(来自 Places 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 中的优先区。

    【讨论】:

      猜你喜欢
      • 2014-07-17
      • 2011-12-13
      • 2011-12-11
      • 2011-08-04
      • 1970-01-01
      • 2020-12-28
      • 1970-01-01
      • 2011-09-23
      • 2013-08-10
      相关资源
      最近更新 更多