【问题标题】:How can i loop through a daterange with different intervals?如何循环遍历具有不同间隔的日期范围?
【发布时间】:2012-05-12 13:06:30
【问题描述】:

我有一个日期范围(从、到),我想循环不同的时间间隔(每天、每周、每月……)

我怎样才能遍历这个日期范围?

更新

感谢您的回答,我想出了以下内容:

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

这将遍历一个日期范围,间隔为周、月或年,并尊重给定间隔的开始和结束。

由于我没有在我的问题中提到这一点,我选择了将我推向正确方向的答案。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 activerecord intervals


    【解决方案1】:

    循环直到from 日期加上1.day1.week1.month 大于to 日期?

     > 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 
    

    【讨论】:

    • [link]stackoverflow.com/questions/501253/…Xenofex回答使用更友好
    • @Sector 那是一样的东西,包裹在一个方法里。
    • 如果遇到像2014-06-30这样的月底,到7月1日是无法加天的,有什么解决办法吗?
    【解决方案2】:

    在 Ruby 1.9 中,我在 Range 上添加了我自己的方法,用于遍历时间范围:

    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
    

    然后,您可以这样称呼它,例如(我的示例使用 Rails 特定的方法: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"]
    

    请注意,此方法使用 Ruby 1.9 约定,如果没有给出块,枚举方法返回一个枚举器,这允许您将枚举器串在一起。

    更新

    我已将 Range#time_step 方法添加到 my personal core_extensions "gem"。如果您想在 Rails 项目中使用它,只需将以下内容添加到您的 Gemfile:

    gem 'core_extensions', github: 'pdobb/core_extensions'
    

    【讨论】:

    【解决方案3】:

    succ 方法在 1.9 范围内已弃用。想要每周做同样的事情,我找到了这个解决方案:

      def by_week(start_date, number_of_weeks)
        number_of_weeks.times.inject([]) { |memo, w| memo << start_date + w.weeks }
      end
    

    这将返回间隔中的周数组。几个月都可以轻松适应。

    【讨论】:

      【解决方案4】:

      你有 Range 对象的 step 方法。 http://ruby-doc.org/core-1.9.3/Range.html#method-i-step

      【讨论】:

      • 你能举个例子吗?您不能随时间迭代,所以这不仅仅是通过1.week 等单步执行的问题。
      • 你可以在这里做一些基本的事情:(Date.current - 5.months .. Date.current).step(7){#code}, (Date.current - 5.months .. Date.current).step(1){#code}
      • 我认为你可以从时间迭代,但它会很慢,因为它会在每秒的范围内创建一个项目
      • 不是在 1.9 中你不能,AFAICT,超高我不是用普通的 int 来做的。
      • 是的......从 1.9 开始,你不能在时间上做范围。 Range 通过在范围的起始值上调用方法 succ 来工作,在 1.9 中,不推荐使用 succ 时间方法...
      猜你喜欢
      • 2010-12-23
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 2020-03-06
      • 2023-02-17
      • 2011-01-10
      相关资源
      最近更新 更多