user266003
user266003

Reputation:

Generating a list of weeks and months given a date-range

Given a date-range, how can I generate a sequential list of

that are included in the date range? For example, if the date-range is Jan 15 - Apr 29, then for the weeks it should be

15 Jan - 17, 18 - 24, 25 - 31 ... 19 Apr - 25, 26 - 29 Apr

where Jan 18th is Sunday, so in this case the week starts on Sunday, but it can also be Monday, doesn't matter. And for the months:

15 Jan - 31, 1 Feb - 28, 1 - 31 March, 1 - 29 Apr

What's the easiest way to do it?

Upvotes: 1

Views: 3559

Answers (2)

user2536065
user2536065

Reputation:

Not sure if this is the easiest way, but it is a way. (Lazy way?)

Months: You start with a range like:

range = (Date.today..6.months.from_now)

Then you can get each month like:

months = range.to_a.map(&:beginning_of_month).uniq
#lookup docs on strftime to get exactly what you want here
months.map { |date| date.strftime('%Y %b') } 

For weeks, you can start with months:

weeks = months.flat_map { |date|
  m_weeks = [date]
  until (week = date + 1.week) && week.month > date.month
    m_weeks << week
  end
  m_weeks
}
#enter some string in strftime (im too lazy to look it up now)
weeks.map { |date| date.strftime('') } 

I didn't test this, but I think it should work. Anyway, there are many ways to do this.

Ok so to get all weeks in the month by weeks Monday - Sunday, you can do something like this:

m_days = (Date.today.beginning_of_month..Date.today.end_of_month).to_a
day_offset = m_days.first.wday - 1
day_offset.times { m_days.unshift(nil) }

Then if you want to get an array of strings that have the first day of the week to the last day of the week you could do this.

weeks = []
m.days.each_slice(7) do |w_days|
  w_days.compact!
  weeks << "#{w_days.first} - #{w_days.last}"
 end

Upvotes: 4

Cary Swoveland
Cary Swoveland

Reputation: 110675

You have two problems:

  • determining the beginning and end of each week between the start date and end date.
  • formatting the dates for display.

I have addressed the first problem only, but have provided all the information required to format the result in any way desired.

We are given:

start_date = "Jan 15, 2015"
end_date   = "Apr 29, 2015"

We then compute the array weeks as follows:

require 'date'

days = (Date.parse(start_date)..Date.parse(end_date)).to_a
weeks = ([days.shift(7-days.first.wday)].concat(
          days.each_slice(7).to_a)).map { |w|
            [w.first, w.last].map { |d| [d.year, d.month, d.day, d.wday] } }
  # => [[[2015, 1, 15, 4], [2015, 1, 17, 6]],
  #     [[2015, 1, 18, 0], [2015, 1, 24, 6]],
  #     [[2015, 1, 25, 0], [2015, 1, 31, 6]],
  #     [[2015, 2,  1, 0], [2015, 2, 7,  6]],
  #     ...  
  #     [[2015, 4, 19, 0], [2015, 4, 25, 6]],
  #     [[2015, 4, 26, 0], [2015, 4, 29, 3]]] 

Each element of weeks corresponds to a week and contains two arrays, one for the first day of the week (a Sunday, for all weeks after the first); the second for the last day of the week (a Saturday for all weeks other than the last). The arrays for individual days contain the year, month (1-12), day of month and day of week (Sunday: 0, Monday: 1,...Saturday: 6).

You can then use the Date class constants (search for "constants" at Date) to format the results.

Upvotes: 2

Related Questions