Подтвердить что ты не робот

Итерация между двумя DateTimes с шагом в один час

Я ищу эффективный способ в Ruby 1.9.x/Rails 3.2.x для итерации между двумя объектами DateTime с шагом в один час.

('2013-01-01'.to_datetime .. '2013-02-01'.to_datetime).step(1.hour) do |date|
   ...
end

Я понимаю, что проблема с этим заключается в том, что 1.hour - это просто количество секунд, но мои попытки конвертировать это в объект DateTime и использовать это как шаг тоже не работают.

Я посмотрел на Опасайтесь Ruby Sugar". Внизу упоминается, что DateTime имеет прямой метод step. Я подтвердил это, запустив methods в объекте DateTime, но я не могу найти документацию на step в DateTime в документах Ruby или Rails.

4b9b3361

Ответ 1

Как и в моем ответе в Как вернуть массив дней и часов из диапазона?, трюк заключается в использовании to_i для работы с секунд с эпохи:

('2013-01-01'.to_datetime.to_i .. '2013-02-01'.to_datetime.to_i).step(1.hour) do |date|
  puts Time.at(date)
end

Обратите внимание, что Time.at() преобразует ваш локальный часовой пояс, поэтому вы можете указать UTC с помощью Time.at(date).utc

Ответ 2

Возможно, поздно, но вы можете сделать это без Rails, например, для шага с часами:

Ruby 2.1.0

require 'time' 

hour_step = (1.to_f/24)

date_time = DateTime.new(2015,4,1,00,00)
date_time_limit = DateTime.new(2015,4,1,6,00)

date_time.step(date_time_limit,hour_step).each{|e| puts e}

2015-04-01T00:00:00+00:00
2015-04-01T01:00:00+00:00
2015-04-01T02:00:00+00:00
2015-04-01T03:00:00+00:00
2015-04-01T04:00:00+00:00
2015-04-01T05:00:00+00:00
2015-04-01T06:00:00+00:00

Или минуты:

#one_minute_step = (1.to_f/24/60)

fifteen_minutes_step = (1.to_f/24/4)

date_time = DateTime.new(2015,4,1,00,00)
date_time_limit = DateTime.new(2015,4,1,00,59)

date_time.step(date_time_limit,fifteen_minutes_step).each{|e| puts e}

2015-04-01T00:00:00+00:00
2015-04-01T00:15:00+00:00
2015-04-01T00:30:00+00:00
2015-04-01T00:45:00+00:00

Надеюсь, это поможет.

Ответ 3

Вот что я недавно придумал:

require 'active_support/all'

def enumerate_hours(start, end_)
  Enumerator.new { |y| loop { y.yield start; start += 1.hour } }.take_while { |d| d < end_ }
end

enumerate_hours(DateTime.now.utc, DateTime.now.utc + 1.day)
# returns [Wed, 20 Aug 2014 21:40:46 +0000, Wed, 20 Aug 2014 22:40:46 +0000, Wed, 20 Aug 2014 23:40:46 +0000, Thu, 21 Aug 2014 00:40:46 +0000, Thu, 21 Aug 2014 01:40:46 +0000, Thu, 21 Aug 2014 02:40:46 +0000, Thu, 21 Aug 2014 03:40:46 +0000, Thu, 21 Aug 2014 04:40:46 +0000, Thu, 21 Aug 2014 05:40:46 +0000, Thu, 21 Aug 2014 06:40:46 +0000, Thu, 21 Aug 2014 07:40:46 +0000, Thu, 21 Aug 2014 08:40:46 +0000, Thu, 21 Aug 2014 09:40:46 +0000, Thu, 21 Aug 2014 10:40:46 +0000, Thu, 21 Aug 2014 11:40:46 +0000, Thu, 21 Aug 2014 12:40:46 +0000, Thu, 21 Aug 2014 13:40:46 +0000, Thu, 21 Aug 2014 14:40:46 +0000, Thu, 21 Aug 2014 15:40:46 +0000, Thu, 21 Aug 2014 16:40:46 +0000, Thu, 21 Aug 2014 17:40:46 +0000, Thu, 21 Aug 2014 18:40:46 +0000, Thu, 21 Aug 2014 19:40:46 +0000, Thu, 21 Aug 2014 20:40:46 +0000, Thu, 21 Aug 2014 21:40:46 +0000]