Я истолковал вопрос следующим образом: «Если задана дата (возможно, сегодняшняя дата), если в этот день ни разу не наступило летнее время, верните nil
. В противном случае верните следующую дату (возможно, такую же дату), чтоначинается как DST и заканчивается как DST ".
require 'date'
def next_dst_date_change(base_date)
base_date_time = base_date.to_time
next_date_time = (base_date+1).to_time
if base_date_time.dst? || next_date_time.dst?
base_date + 1.step.find { |n| (base_date + n).to_time.dst? == false } - 1
end
end
См. Date # to_time , Time # dst? , Числовой # step и Enumerable # find .
Примеры
d0 = Date.today
#=> #<Date: 2018-09-24 ((2458386j,0s,0n),+0s,2299161j)>
next_dst_date_change(d0)
#=> #<Date: 2018-11-04 ((2458427j,0s,0n),+0s,2299161j)>
d1 = Date.new(2018, 11, 04)
#=> #<Date: 2018-11-04 ((2458427j,0s,0n),+0s,2299161j)>
next_dst_date_change(d0)
#=> #<Date: 2018-11-04 ((2458427j,0s,0n),+0s,2299161j)>
d2 = d0 + 90
#=> #<Date: 2018-12-23 ((2458476j,0s,0n),+0s,2299161j)>
next_dst_date_change(d2)
#=> nil
d3 = d0 + 365
#=> #<Date: 2019-09-24 ((2458751j,0s,0n),+0s,2299161j)>
next_dst_date_change(d3)
#=> #<Date: 2019-11-03 ((2458791j,0s,0n),+0s,2299161j)>
d4 = Date.new(2018, 3, 10)
#=> #<Date: 2018-03-10 ((2458188j,0s,0n),+0s,2299161j)>
next_dst_date_change(d4)
#=> nil
d5 = Date.new(2018, 3, 11)
next_dst_date_change(d5)
#=> #<Date: 2018-11-04 ((2458427j,0s,0n),+0s,2299161j)>
Чтобы ускорить процесс, можно выполнить бинарный поиск, чтобы определить следующую дату изменения DST-non_DST, используя Range # bsearch .Я предположил, что летнее время заканчивается некоторое время до 1 декабря каждого года.
def next_dst_date_change(base_date)
base_date_time = base_date.to_time
next_date_time = (base_date+1).to_time
if base_date_time.dst? || next_date_time.dst?
diff = (Date.new(base_date.year, 12, 1) - base_date).to_i
base_date + (1..diff).bsearch { |n| !(base_date + n).to_time.dst? } - 1
end
end