-2

I have a range with a start_date, end_date and I want to get the same day of each month for the whole range, so here starting on the 30th of January I should get the 30th of each month:

start_date = Date.new(2019, 1, 30)
end_date = Date.new(2019, 12, 30)

range = (start_date...end_date)
dates = range.step(30).map(&:to_date)

dates
#=> [Wed, 30 Jan 2019,
#    Fri, 01 Mar 2019,
#    Sun, 31 Mar 2019,
#    Tue, 30 Apr 2019,
#    Thu, 30 May 2019,
#    Sat, 29 Jun 2019,
#    Mon, 29 Jul 2019,
#    Wed, 28 Aug 2019,
#    Fri, 27 Sep 2019,
#    Sun, 27 Oct 2019,
#    Tue, 26 Nov 2019,
#    Thu, 26 Dec 2019]

I was using something like this for weeks but with months when you get to February for example it of course fails, so I would have to adjust to 28th.

I know I could loop and look at the month and do adjustments based on the start_date but it feels like a bad idea.

Stefan
  • 109,145
  • 14
  • 143
  • 218
eXa
  • 618
  • 8
  • 18
  • It's a bit unfortunate that in your example, `30` is both, the day of the month and the increment value for `step`. – Stefan Oct 23 '19 at 09:08
  • BTW it's not just February. Note that most of the other dates are off, too. You can't move from month to month by adding 30 days because only 4 out of the 12 months have exactly 30 days. – Stefan Oct 23 '19 at 09:17

1 Answers1

4

I think you can use either active support:

require 'active_support/time'
start_date = Date.parse('2019-10-31')
12.times.map { |i| start_date + i.month }

=> [
 Thu, 31 Oct 2019,
 Sat, 30 Nov 2019,
 Tue, 31 Dec 2019,
 Fri, 31 Jan 2020,
 Sat, 29 Feb 2020,
 Tue, 31 Mar 2020,
 Thu, 30 Apr 2020,
 Sun, 31 May 2020,
 Tue, 30 Jun 2020,
 Fri, 31 Jul 2020,
 Mon, 31 Aug 2020,
 Wed, 30 Sep 2020
]

or adjust: #next_month:

require 'date'
Date.parse('2019-10-31').next_month # => Sat, 30 Nov 2019
Yurii
  • 682
  • 4
  • 8
  • This is perfect, thank you! Yeah I had found `.next_month` but after the 28th of Feb it would switch to 28 everywhere. – eXa Oct 23 '19 at 21:47
  • Any suggestion on how to calculate the number of month between two dates? "Best" I've found is using `30.4375` and the number of days doing a count on the range which will have precision issues. – eXa Oct 24 '19 at 00:52
  • 1
    for number of months you can adjust this snippet: `date1 = Date.parse('2019-10-24'); date2 = Date.parse('2019-11-25'); (date2.year * 12 + date2.month) - (date1.year * 12 + date1.month)`. Borrowed from [Find number of months between two Dates in Ruby on Rails ](https://stackoverflow.com/questions/9428605/find-number-of-months-between-two-dates-in-ruby-on-rails) – Yurii Oct 24 '19 at 02:05