Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4: How to add/subtract multiples of quarters to Date?

To get the start and end dates of the current quarter one could do:

start_of_curr_quarter = Time.current.to_date.beginning_of_quarter
end_of_curr_quarter = start_of_curr_quarter.end_of_quarter

To get the dates of the previous quarter, this seems to be a reasonable approach:

end_of_prev_quarter = Time.current.to_date.beginning_of_quarter - 1
start_of_prev_quarter = end_of_prev_quarter.beginning_of_quarter

I would like to generalize this. How would you implement the following function in Rails 4?

def quarter_dates(quarter_offset)
  # --------------------------------------------  
  #    quarter_offset        return value
  # --------------------------------------------
  #          0           current quarter dates
  #          1             prev quarter dates
  #          2         before prev quarter dates
  #         ...                   ...

  # Implementation goes here...

  [start_of_quarter, end_of_quarter]
end
like image 214
Misha Moroshko Avatar asked Jun 12 '14 11:06

Misha Moroshko


3 Answers

I would do it this way:

def quarter_dates(offset)
  date = Date.today << (offset * 3)
  [date.beginning_of_quarter, date.end_of_quarter]
end

puts quarter_dates(0) #=> [Tue, 01 Apr 2014, Mon, 30 Jun 2014]
puts quarter_dates(1) #=> [Wed, 01 Jan 2014, Mon, 31 Mar 2014]
puts quarter_dates(9) #=> [Sun, 01 Jan 2012, Sat, 31 Mar 2012]
like image 183
spickermann Avatar answered Oct 02 '22 16:10

spickermann


I assume positive offsets for future and negative offsets for past. You can make negative offsets for future and positive offsets for the past by replacing months_since with months_ago.

You can also optionally pass a day if you wish to get quarters relative to it.

def quarter_dates offset=0, date_day=Date.today
  temp = date_day.months_since(3 * offset)
  [temp.beginning_of_quarter, temp.end_of_quarter]
end

Test:

quarter_dates # => [Tue, 01 Apr 2014, Mon, 30 Jun 2014] 
quarter_dates -1 # => [Wed, 01 Jan 2014, Mon, 31 Mar 2014]
quarter_dates -2, Date.new(2013,1,1) # => [Sun, 01 Jul 2012, Sun, 30 Sep 2012] 
quarter_dates 1, Date.new(2013,9,30) # => [Tue, 01 Oct 2013, Tue, 31 Dec 2013]
like image 40
Tamer Shlash Avatar answered Oct 02 '22 16:10

Tamer Shlash


Using Rails my solution is

def quarter_dates(quarter_offset = 0)
  quarter_start = Time.now.to_date.beginning_of_quarter - (3 * quarter_offset).months
  quarter_end = quarter_start.end_of_quarter
  [quarter_start,quarter_end]
end

I personally would prefer to use + (3*quarter_offset).months and use negative offsets for previous months though.

like image 21
Martin M Avatar answered Oct 02 '22 16:10

Martin M