С 2007 года в большинстве юрисдикций в Соединенных Штатах и Канаде переход на летнее время («летнее время») начался в 2:00 во второе воскресенье марта и завершился в 2:00 в первое воскресенье ноября.В Мексике летнее время начинается в 2:00 утра в первое воскресенье апреля и заканчивается в 2:00 утра в последнее воскресенье октября.Опыт может быть разным в других частях света. 1
При наличии объекта Time
(возможно, вычисляемого из строкового представления времени) ваш код возвращает второй Time
объект, равныйдо момента, когда произойдет следующее изменение, с летнего времени на ЗППП или наоборот (т. е. в тех частях Соединенных Штатов и Канады, которые приняли летнее время).Нет необходимости жестко связывать эти даты.Вычисление может быть выполнено следующим образом.
require 'time'
def dst_datechange(time)
year = time.year
if time.dst?
start_std(year)
else
year += 1 if time >= Time.new(year, 11)
start_dst(year)
end
end
def start_std(year)
date = Date.new(year, 11)
date += (7-date.wday) % 7
Time.new(date.year, date.month, date.day, 2)
end
def start_dst(year)
date = Date.new(year, 3, 8)
date += (7-date.wday) % 7
Time.new(date.year, date.month, date.day, 2)
end
['June 17, 2018 1:00pm', 'November 4, 2018 12:59am', 'November 4, 2018 1:00am',
'March 10, 2019 1:59am', 'March 10, 2019 2:00am'].
each do |s|
t = DateTime.strptime(s, '%B %e, %Y %l:%M%P').to_time
t = Time.new(t.year, t.month, t.day, t.hour, t.min, t.sec)
puts "#{s}: #{ dst_datechange(t) }"
end
June 17, 2018 1:00pm: 2018-11-04 02:00:00 -0800
November 4, 2018 12:59am: 2018-11-04 02:00:00 -0800
November 4, 2018 1:00am: 2019-03-10 03:00:00 -0700
March 10, 2019 1:59am: 2019-03-10 03:00:00 -0700
March 10, 2019 2:00am: 2019-11-03 02:00:00 -0800
Обратите внимание, что первый, второй и последний примеры возвращают время, час которого равен 2
.Это на самом деле через час после того, как время изменилось.Два других примера возвращают час 3
, то есть мгновение после изменения времени.Примечание:
Time.new(2019, 3, 10, 2)
#=> 2019-03-10 03:00:00 -0700
Time.parse('March 10, 2019 2:00am')
#=> 2019-03-10 03:00:00 -0700
В будущем диапазоны дат перехода на летнее время могут измениться (как они это делали в 2007 году), или DST может быть исключен в целом .Следовательно, в производственном коде было бы целесообразно рассмотреть эти возможности.Предполагая, что метод Time # dst? будет продолжать существовать, Time.new(year,6).dst?
должен сообщить нам, если у нас все еще есть летнее время, и если это так, можно искать изо дня в день, чтобы увидеть, когда происходят изменения времени.
1. Источник