How can i loop through a daterange with different intervals?

ⅰ亾dé卋堺 提交于 2019-11-30 14:07:51

问题


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.


回答1:


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 



回答2:


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'



回答3:


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.




回答4:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!