LoginSignup
38
31

More than 5 years have passed since last update.

Rubyで年・月・週単位で日付をループさせる

Last updated at Posted at 2016-02-09

通常の日付のループ処理

RubyのDateクラスは先頭の日付と末尾の日付を繰り返し処理出来る仕組みがあります。

head = Date.new(2016, 1)
tail = Date.new(2016, 12)

# 1日ずつループ
(head..tail).each { |date| p date.strftime('%Y%m%d') }
# => '20160101', '20160102', '20160103', ...

# n日の間隔でループ
head.step(tail, 5).each { |date| p date.strftime('%Y%m%d') }
# => '20160101', '20160106', '20160111', ...

これはこれで、とても便利な機能なのですが、ループのstepの幅は日単位でしか指定することが出来ません。

年・月・週単位でループさせる

Enumeratorインスタンスを生成することで、任意の間隔でループさせる処理を書くことが出来るようになります。

e = Enumerator.new do |yielder|
  head = Date.new 2016, 1
  tail = Date.new 2016, 12

  while head <= tail
    yielder << head
    head = head.next_month # ここをhead.next_weekやhead.next_yearに変えることで年毎や週毎のループに出来る
  end
end

e.each { |date| p date.strftime('%Y%m%d') }
# => '20160101', '20160201', '20160301', ...

ほんの少し解説

yielderに対して<< argという形でメソッドを呼び出すとargeachのブロック引数に渡されます。
上記のサンプルコードでは、yielder << headとなっているので、head(whileループの中でカウントアップされている日付)がeachのブロック引数に渡されていることになります。

便利に使う

下記のようなrefinementを利用して、Dateクラスを拡張すると便利です。
active_supportを使うこと前提のコードです)

require 'date'
require 'active_support/all'

module DateExtender
  refine Date do
    def step_by_unit(tail, unit = :day, step = 1)
      head = self.dup

      Enumerator.new do |yielder|
        while head <= tail
          yielder << head
          head += step.send(unit)
        end
      end
    end
  end
end

using DateExtender

# week by
head = Date.new(2016, 1)
tail = Date.new(2016, 1).end_of_month
head.step_by_unit(tail, :week).each { |date| p date.strftime('%Y%m%d') }
# => '20160101', '20160108', '20160115', ...

# month by
head = Date.new(2016, 1)
tail = Date.new(2016, 4)
head.step_by_unit(tail, :month).each { |date| p date.strftime('%Y%m%d') }
# => '20160101', '20160201', '20160301', ...

# year by
head = Date.new(2016)
tail = Date.new(2020)
head.step_by_unit(tail, :year).each { |date| p date.strftime('%Y%m%d') }
# => '20160101', '20170101', '20180101', ...
38
31
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
31