【问题标题】:How to get time_zone_options_for_select with DST offsets?如何使用 DST 偏移量获取 time_zone_options_for_select?
【发布时间】:2011-09-11 22:37:23
【问题描述】:

ActionView::Helpers::FormOptionsHelper 提供time_zone_options_for_select 来获取选择控件的选项列表,其中包括所有时区及其UTC 偏移量。我遇到的问题是如何让它在夏令时生效时显示正确的偏移量?

例如,美国山区时间通常是 -7 UTC,但在夏季,它实际上是 -6 UTC。有没有办法让该列表正确反映这一点?

【问题讨论】:

  • @stevec - 不知道你为什么在这里发布赏金而不是提出问题,但也请滚动到the timezone tag 的底部并阅读有关 Rails 时区的部分。谢谢。
  • @stevec - 我添加了一个我相信足以回答您的问题的答案。

标签: ruby timezone dst activesupport


【解决方案1】:

TL;DR

您收到的时区数据是“正确的”,因为 ActiveSupport::TimeZoneTZInfo::Timezone 实例不会对当前日期做出假设,因此对它们应用 DST 在这些对象的责任。

注意到这个问题是因为time_zone_options_for_select 的默认模型ActiveSupport::TimeZone 在调用#to_s 时会返回偏移字符串,如果该位置当前正在观察夏令时,将不正确。无法修复选项中生成的字符串值,甚至无法从中删除偏移量。

如果这不可接受,您需要跳过使用time_zone_options_for_select,而使用options_for_select,并自己生成选项。

一些调查

time_zone_options_for_select 使用::ActiveSupport::TimeZone 作为默认的model 参数,因此手动传递它不会改变您的结果。为了构造选择框的选项,该方法将以[time_zone.to_s, time_zone.name] 的格式构造一个元组数组,以便将其传递给更通用的options_for_select 方法。在这种情况下,time_zone::ActiveSupport::TimeZone 的一个实例。

这里的重要因素是,从概念上讲,这个时区实例对象与“当前日期”的概念完全无关/背道而驰。时区的定义(严格来说)与当前日期无关。我们可以像这样确认这个“不使用 DST”的问题:

::ActiveSupport::TimeZone.all.find { |tz| tz.name == "Adelaide" }.utc_offset
=> 34200 # 9 hours and 30 minutes, in seconds

阿德莱德的非 DST 时区是 ACST(澳大利亚中部标准时间),即 GMT+9.5。目前(在撰写本文时),阿德莱德在 DST,这意味着他们在 ACDT(澳大利亚中部夏令时间),即 GMT+10.5。

::ActiveSupport::TimeZone.all.find { |tz| tz.name == "Adelaide" }.now.utc_offset
=> 37800 # 10 hours and 30 minutes, in seconds

这里的关键区别本质上是我上面概述的 - ActiveSupport::TimeZone 实例只是关注当前日期。该类本身是一个围绕 TZInfo::DataTimezone 实例的便捷包装器,它在当前日期有类似的意见 - 没有。

如果您注意到,在上面的第二个代码 sn-p 中,我们在调用 #utc_offset 之前在时区对象上调用了 #now。这将返回一个 ActiveSupport::TimeWithZone 实例,其中包括有关时区以及当前日期的信息 - 因此我们得到一个偏移量,它反映了当前日期应该包括 DST 偏移量这一事实。

因此,这里唯一的问题是在 ActiveSupport::TimeZone 实例上的 #to_s 的返回值中包含 UTC 偏移字符串在这种情况下有点误导。包含它是因为它是该时区的“基本”UTC 偏移量。

资源:

【讨论】:

    【解决方案2】:

    我有类似的问题,但最终使用了这个

    time_zone_select('time_zone', TZInfo::Timezone.us_zones, 
                                         :default => "America/Los_Angeles", 
                                         :model => TZInfo::Timezone
    

    您找到更好的解决方案了吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-06
      • 2012-10-30
      • 2011-08-04
      • 2010-11-06
      • 2019-08-29
      • 2015-08-12
      • 2021-04-21
      • 2016-12-07
      相关资源
      最近更新 更多