Ruby/Rails中的夏令时开始和结束日期

use*_*827 5 ruby timezone ruby-on-rails dst timezone-offset

我正在开发一个Rails应用程序,我需要在给定特定偏移量或时区的情况下找到夏令时开始和结束日期.

我基本上在我的数据库中保存从用户的浏览器("+3","-5")收到的时区偏移量,并且由于夏令时,我想在它改变时修改它.

我知道Time实例变量具有dst?isdst方法,如果存储在它们中的日期是夏令时,则返回true或false.

 > Time.new.isdst
 => true 
Run Code Online (Sandbox Code Playgroud)

但是使用它来查找夏令时开始和结束日期将占用太多资源,我还必须为每个时区偏移执行此操作.

我想知道更好的方法.

Bea*_*ech 7

好的,基于你所说的和@ dhouty的回答:

您希望能够提供偏移量并获取一组日期以了解是否存在DST偏移量.我建议最终得到一个由两个DateTime对象组成的范围,因为它很容易在Rails中用于很多目的......

require 'tzinfo'

def make_dst_range(offset)

  if dst_end = ActiveSupport::TimeZone[offset].tzinfo.current_period.local_end
     dst_start = ActiveSupport::TimeZone[offset].tzinfo.current_period.local_start
     dst_range = dst_start..dst_end
  else
     dst_range = nil
  end

end
Run Code Online (Sandbox Code Playgroud)

现在你有一个方法,除了采用ActiveSupport附带的糖之外,还可以做一些偏移.你可以这样做:

make_dst_range(-8)
#=> Sun, 08 Mar 2015 03:00:00 +0000..Sun, 01 Nov 2015 02:00:00 +0000

make_dst_range('America/Detroit')
#=> Sun, 08 Mar 2015 03:00:00 +0000..Sun, 01 Nov 2015 02:00:00 +0000

make_dst_range('America/Phoenix')
#=> nil     #returns nil because Phoenix does not observe DST

my_range = make_dst_range(-8)
#=> Sun, 08 Mar 2015 03:00:00 +0000..Sun, 01 Nov 2015 02:00:00 +0000
Run Code Online (Sandbox Code Playgroud)

今天恰好是8月29日所以:

my_range.cover?(Date.today)
  #=> true
my_range.cover?(Date.today + 70)
  #=> false
my_range.first
  #=> Sun, 08 Mar 2015 03:00:00 +0000
  #note that this is a DateTime object. If you want to print it use:
my_range.first.to_s
  #=> "2015-03-08T03:00:00+00:00"
my_range.last.to_s
  #=> "2015-11-01T02:00:00+00:00"
Run Code Online (Sandbox Code Playgroud)

ActiveSupport为您提供各种显示内容:

my_range.first.to_formatted_s(:short)
  #=> "08 Mar 03:00"
my_range.first.to_formatted_s(:long)
  #=> "March 08, 2015 03:00"
my_range.first.strftime('%B %d %Y')
   #=> "March 08 2015"
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,只有偏移是完全可行的,但正如我所说,偏移并不能告诉你一切,所以你可能想要抓住它们的实际时区并将其存储为字符串,因为该方法将很乐意接受该字符串和仍然给你日期范围.即使您只是在您的区域和他们的区域之间获得时间偏移,您也可以轻松地将其校正为UTC偏移:

my_offset = -8
their_offset = -3
utc_offset = my_offset + their_offset
Run Code Online (Sandbox Code Playgroud)

  • 这个答案通常每年两次获得几分.大声笑 (2认同)

dho*_*uty 6

您可能正在寻找的是TZInfo::TimezonePeriod. 具体来说,方法local_start/utc_startlocal_end/ utc_end

给定一个时区偏移量,你可以得到一个TZInfo::TimezonePeriod对象

ActiveSupport::TimeZone[-8].tzinfo.current_period
Run Code Online (Sandbox Code Playgroud)

或者如果你有一个时区名称,你也可以得到一个TZInfo::TimezonePeriod对象

ActiveSupport::TimeZone['America/Los_Angeles'].tzinfo.current_period
Run Code Online (Sandbox Code Playgroud)