Tintin81
Tintin81

Reputation: 10207

How to output a date range for each quarter of a year in Ruby?

Thanks to some people on this board I was able to come up with a function that returns a number of date ranges:

years = [2013, 2012, 2011, 2010, 2009]

def month_ranges
  years.flat_map { |y|
    12.downto(1).map { |m| Date.new(y,m,1)..Date.new(y,m,-1) }
  }
end

# => 

[
  01 Dec 2013..31 Dec 2013, 
  01 Nov 2013..31 Nov 2013, 
  01 Oct 2013..31 Oct 2013, 
  01 Sep 2013..31 Sep 2013,
  01 Aug 2013..31 Aug 2013,
  ....
]

Now, is there a way to return the four quarters of a year as well?

So the output will be something like:

# => 

[
  01 Oct 2013..31 Dec 2013,
  01 Jul 2013..31 Sep 2013,
  01 Apr 2013..31 Jun 2013,
  01 Jan 2013..31 Mar 2013
]

(Note: If a month has 30 or 31 days doesn't really matter in this case.)

Thanks to anyone who can help.

Upvotes: 1

Views: 1232

Answers (4)

Peter de Ridder
Peter de Ridder

Reputation: 2399

You can use beginning_of_quarter and end_of_quarter to define quarters.

For example, if I want to group a date_range according to quarters I could do the following:

((Date.today - 1.year)..Date.today).group_by(&:beginning_of_quarter)

The keys in this case are the beginning of each quarter:

((Date.today - 1.year)..Date.today).group_by(&:beginning_of_quarter).keys
=> [Sun, 01 Jul 2012, Mon, 01 Oct 2012, Tue, 01 Jan 2013, Mon, 01 Apr 2013, Mon, 01 Jul 2013]

Upvotes: 4

Stefan
Stefan

Reputation: 114178

This should work (based on month_ranges, i.e. last quarter comes first):

def quarter_ranges
  years.flat_map { |y|
    3.downto(0).map { |q|
      Date.new(y, q * 3 + 1, 1)..Date.new(y, q * 3 + 3, -1)
    }
  }
end

Or a bit more verbose and maybe easier to understand:

def quarter_ranges
  years.flat_map { |y|
    [
      Date.new(y, 10, 1)..Date.new(y, 12, -1),
      Date.new(y,  7, 1)..Date.new(y,  9, -1),
      Date.new(y,  4, 1)..Date.new(y,  6, -1),
      Date.new(y,  1, 1)..Date.new(y,  3, -1)
    ]
  }
end

Upvotes: 4

jbr
jbr

Reputation: 6258

I'd do something like:

require 'date'
def quarters(y)
  q = []
  (1..4).each do |s|
    q << (Date.new(y, s * 3 - 1, 1)..Date.new(y, s * 3, -1))
  end
  return q
end

Upvotes: 1

Pierre-Louis Gottfrois
Pierre-Louis Gottfrois

Reputation: 17631

What about something like this:

> now = Time.now.beginning_of_month
 => 2013-09-01 00:00:00 +0200
> now..(now + 3.months)
 => 2013-09-01 00:00:00 +0200..2013-12-01 00:00:00 +0100

Upvotes: 2

Related Questions