Reputation:
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
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
Reputation: 110675
You have two problems:
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