2009-02-01 47 views
30

有沒有辦法在Ruby中迭代時間範圍,並設置增量?迭代Ruby時間對象與增量

這裏是我想要做什麼的想法:

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

可以遍歷時間的對象,但它返回每秒兩者之間。我真正需要的是一種設置偏移量或增量(如分鐘,小時等)的方法

這是內置到Ruby中,還是有一個像樣的插件可用?

回答

55

此前1.9,你可以使用Range#step

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

然而,這種策略是相當緩慢的,因爲它會叫Time#succ 3600次。相反, 由dolzenko在his answer指出,更有效的解決方案是使用一個簡單的循環:如果您使用Rails的

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

你可以1.hour,這是顯著更具可讀性替代3600。

+4

範圍#步驟對於Ruby 1.9.2p180和1.9.3中的Time對象不起作用。它說:TypeError:不能從Time迭代。 – prekageo 2012-02-22 18:40:55

+0

@prekageo謝謝,更新。 – 2012-02-22 21:25:17

36

如果您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 

但是,這也可以做更簡單,更高效的(即沒有所有的類型轉換) loop:

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

Range#step method在這種情況下非常慢。使用begin..end,正如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 
在軌

如果。