I have a daterange (from, to) that i want loop through an different intervals (daily, weekly, monthly, ...)
How can i loop through this dateranges?
Update
Thanks for your answers, i came up with the following:
interval = 'week' # month, year
start = from
while start < to
stop = start.send("end_of_#{interval}")
if stop > to
stop = to
end
logger.debug "Interval from #{start.inspect} to #{stop.inspect}"
start = stop.send("beginning_of_#{interval}")
start += 1.send(interval)
end
This will loop through a date range with intervals week, month or year and respects the beginning and end of the given interval.
Since i did not mention this in my question i choosed the answer that pushed me into the right direction.
Loop until the from
date plus 1.day
, 1.week
, or 1.month
is greater than the to
date?
> from = Time.now
=> 2012-05-12 09:21:24 -0400
> to = Time.now + 1.month + 2.week + 3.day
=> 2012-06-29 09:21:34 -0400
> tmp = from
=> 2012-05-12 09:21:24 -0400
> begin
?> tmp += 1.week
?> puts tmp
?> end while tmp <= to
2012-05-19 09:21:24 -0400
2012-05-26 09:21:24 -0400
2012-06-02 09:21:24 -0400
2012-06-09 09:21:24 -0400
2012-06-16 09:21:24 -0400
2012-06-23 09:21:24 -0400
2012-06-30 09:21:24 -0400
=> nil
In Ruby 1.9, I added my own method on Range for stepping through time ranges:
class Range
def time_step(step, &block)
return enum_for(:time_step, step) unless block_given?
start_time, end_time = first, last
begin
yield(start_time)
end while (start_time += step) <= end_time
end
end
Then, you can call this like, e.g. (My example uses a Rails specific method: 15.minutes):
irb(main):001:0> (1.hour.ago..Time.current).time_step(15.minutes) { |time| puts time }
2012-07-01 21:07:48 -0400
2012-07-01 21:22:48 -0400
2012-07-01 21:37:48 -0400
2012-07-01 21:52:48 -0400
2012-07-01 22:07:48 -0400
=> nil
irb(main):002:0> (1.hour.ago..Time.current).time_step(15.minutes).map { |time| time.to_s(:short) }
=> ["01 Jul 21:10", "01 Jul 21:25", "01 Jul 21:40", "01 Jul 21:55", "01 Jul 22:10"]
Notice that this method uses the Ruby 1.9 convention where enumeration methods return an enumerator if no block is given, which allows you to string enumerators together.
UPDATE
I've added the Range#time_step method to my personal core_extensions
"gem". If you'd like to utilize this in your Rails project, just add the following to your Gemfile:
gem 'core_extensions', github: 'pdobb/core_extensions'
The succ method is deprecated in 1.9 range. Wanting to do the same thing by week, I came to this solution :
def by_week(start_date, number_of_weeks)
number_of_weeks.times.inject([]) { |memo, w| memo << start_date + w.weeks }
end
This return an array of week in the interval. Easily adaptable for months.
You have the step method on the Range object. http://ruby-doc.org/core-1.9.3/Range.html#method-i-step
来源:https://stackoverflow.com/questions/10564011/how-can-i-loop-through-a-daterange-with-different-intervals