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

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

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

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

  > Time.new.isdst => true 

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

我想知道更好的方法。

好的,建立在你所说的和@ 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 

现在你有一个方法,除了采用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 

今天恰好是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" 

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" 

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

 my_offset = -8 their_offset = -3 utc_offset = my_offset + their_offset 

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

TZInfo::TimezonePeriod区偏移量,您可以获得TZInfo::TimezonePeriod对象

 ActiveSupport::TimeZone[-8].tzinfo.current_period 

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

 ActiveSupport::TimeZone['America/Los_Angeles'].tzinfo.current_period