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

Итерация над объектом Ruby Time с дельта

Есть ли способ перебрать диапазон времени в Ruby и установить delta?

Вот идея того, что я хотел бы сделать:

for hour in (start_time..end_time, hour)
    hour #=> Time object set to hour
end

Вы можете выполнять итерацию по объектам Time, но она возвращает каждую секунду между ними. Мне действительно нужно установить смещение или дельта (например, минуту, час и т.д.).

Является ли это встроенным в Ruby, или есть доступный плагин?

4b9b3361

Ответ 1

До 1.9 можно использовать Range#step:

(start_time..end_time).step(3600) do |hour|
  # ...
end

Однако эта стратегия довольно медленная, так как она назовёт Time#succ 3600 раз. Вместо, как отметил dolzenko в его ответе, более эффективным решением является использование простой петли:

hour = start_time
while hour < end_time
  # ...
  hour += 3600
end

Если вы используете Rails, вы можете заменить 3600 на 1.hour, что значительно читаемо.

Ответ 2

Если ваши start_time и end_time на самом деле являются экземплярами класса Time, тогда решение с использованием Range#step было бы крайне неэффективно, так как оно повторяло бы каждую секунду в этом диапазоне с помощью Time#succ. Если вы конвертируете свое время в целые числа, будет использовано простое добавление, но таким образом вы получите что-то вроде:

(start_time.to_i..end_time.to_i).step(3600) do |hour|
  hour = Time.at(hour)     
  # ...
end

Но это также можно сделать с помощью более простого и эффективного (т.е. без всех преобразований типов):

hour = start_time
begin
  # ...      
end while (hour += 3600) < end_time

Ответ 3

Метод шага диапазона # в этом случае очень медленный. Используйте begin..end while, как dolzenko отправил здесь.

Вы можете определить новый метод:

  def time_iterate(start_time, end_time, step, &block)
    begin
      yield(start_time)
    end while (start_time += step) <= end_time
  end

то

start_time = Time.parse("2010/1/1")
end_time = Time.parse("2010/1/31")
time_iterate(start_time, end_time, 1.hour) do |t|
  puts t
end

если в рельсах.