使用delta迭代Ruby Time对象

lpwwtiir  于 2023-08-04  发布在  Ruby
关注(0)|答案(4)|浏览(123)

有没有一种方法可以在Ruby中迭代一个时间范围,并设置增量?
以下是我想做的一个想法:

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

字符串
您可以遍历Time对象,但它会在两个对象之间每秒返回一次。我真正需要的是一种设置偏移量或增量(如分钟、小时等)的方法
这是Ruby内置的吗,还是有一个不错的插件可用?

mfuanj7w

mfuanj7w1#

在1.9之前,可以使用Range#step

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

字符串
但是,这种策略非常慢,因为它会调用Time#succ 3600次。相反,正如dolzenko在his answer中指出的那样,更有效的解决方案是使用一个简单的循环:

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


如果你使用Rails,你可以用1.hour代替3600,它的可读性更好。

inn6fuwd

inn6fuwd2#

如果你的start_timeend_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

dzjeubhm

dzjeubhm3#

Range#step方法在这种情况下非常慢。使用开始..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


如果在轨道中。

bkhjykvo

bkhjykvo4#

以下是每种情况的通用函数:

def split_time_by_periods(start_time, end_time, time_step)
  return to_enum(:split_time_by_periods, start_time, end_time, time_step) unless block_given?

  start_time = start_time.to_i
  end_time = end_time.to_i
  current_time = start_time

  while current_time < end_time
    period_end = [current_time + time_step, end_time].min
    yield(Time.at(current_time).utc, Time.at(period_end).utc)

    current_time += time_step
  end
end

字符串
使用方法:

split_time_by_periods(Time.now, Time.now + 1.hour + 30.minutes, 1.hour).to_a
 # => [[2023-07-26 08:00:26 UTC, 2023-07-26 09:00:26 UTC], [2023-07-26 09:00:26 UTC, 2023-07-26 09:30:26 UTC]]

split_time_by_periods(Time.now, Time.now + 1.day, 5.hours) do |period_start, period_end|
 # ...
end

split_time_by_periods(Time.now, Time.now + 1.day, 5.hours).map do |period_start, period_end|
 # ...
end

相关问题