def first_day_of_month(selected_date)
selected_date.strftime('%Y-%m-01').to_date
end
def offset(selected_date)
wday = first_day_of_month(selected_date).wday
wday == 0 ? 6 : (wday - 1)
end
def start_date(selected_date)
first_day_of_month(selected_date) - offset(selected_date)
end
def end_date(selected_date)
(first_day_of_month(selected_date) - offset(selected_date)) + 41
end
def date_range_by_week(selected_date)
date_range_by_week = []; date_range = [];
start_date(selected_date).upto(end_date(selected_date)) { |date| date_range << date }
until date_range.empty?
week = []
7.times do |i|
week << date_range.shift
end
date_range_by_week << week
end
date_range_by_week
end
def calender_header
puts "
.-----------------------------------------------------------------------------,
| monday | tuesday | wednesday| thursday | friday | saturday | sunday |
"
end
def highlight?(day, date)
day == Date.today or day == date
end
def paint_calendar(date)
calender_header
date_range_by_week(date).each_with_index do |week, i|
next if week[0].month > date.month or week[0].year != date.year
print ".--week[##{week[0].strftime('%W')}]-----------------------------------------------------------------.\n| "
7.times do |i|
daystr = week[i].strftime('%b %d')
spacer = highlight?(week[i], date) ? '==' : ' '
print "#{spacer}#{daystr}#{spacer}|"
print "\n" if i == 6
end
end
puts "+-----------------------------------------------------------------------------+"
end
# >> paint_calendar Date.today # # # # # .-----------------------------------------------------------------------------, # | monday | tuesday | wednesday| thursday | friday | saturday | sunday | # .--week[#08]-----------------------------------------------------------------. # | Feb 23 | Feb 24 | Feb 25 | Feb 26 | Feb 27 | Feb 28 | Mar 01 | # .--week[#09]-----------------------------------------------------------------. # | Mar 02 | Mar 03 | Mar 04 | Mar 05 | Mar 06 | Mar 07 | Mar 08 | # .--week[#10]-----------------------------------------------------------------. # | Mar 09 | Mar 10 | Mar 11 | Mar 12 | Mar 13 | Mar 14 | Mar 15 | # .--week[#11]-----------------------------------------------------------------. # | Mar 16 | Mar 17 | Mar 18 | Mar 19 | Mar 20 | Mar 21 | Mar 22 | # .--week[#12]-----------------------------------------------------------------. # | Mar 23 | Mar 24 |==Mar 25==| Mar 26 | Mar 27 | Mar 28 | Mar 29 | # .--week[#13]-----------------------------------------------------------------. # | Mar 30 | Mar 31 | Apr 01 | Apr 02 | Apr 03 | Apr 04 | Apr 05 | # +-----------------------------------------------------------------------------+ # => nil # >>
Refactorings
No refactoring yet !
Marc-Andre
March 25, 2009, March 25, 2009 17:26, permalink
I'm presuming you're coding in rails, or at least using 'activesupport', so there is no need for your 'first_day_of_month' method. Use DateTime.beginning_of_month. Also, you were looking for Array.in_groups_of (activesupport) or Enumerable.group_by (ruby 1.9). Here's the result:
def offset(selected_date) wday = selected_date.beginning_of_month.wday wday == 0 ? 6 : (wday - 1) end def start_date(selected_date) selected_date.beginning_of_month - offset(selected_date) end def end_date(selected_date) (selected_date.beginning_of_month - offset(selected_date)) + 41 end def date_range_by_week(selected_date) (start_date(selected_date)..end_date(selected_date)).to_a.in_groups_of(7) end
Marc-Andre
March 25, 2009, March 25, 2009 17:44, permalink
And if you don't need those extra methods, it's really a two line job, and you can change the beginning of the week easily:
def date_range_by_week(selected_date) first_in_calendar = selected_date.beginning_of_month.next_week(:monday) - 7 (first_in_calendar...(first_in_calendar+7*6)).to_a.in_groups_of(7) end
Bonobo
March 25, 2009, March 25, 2009 19:12, permalink
Lesson learned! (Read the Ruby/Rails docs closer) Thanks like 9000 times, Marc-André
bob
March 25, 2009, March 25, 2009 19:57, permalink
def date_range_by_week(selected_date) (start_date(selected_date)..end_date(selected_date)).enum_slice(7).to_a end
I'm mainly interested in optimizing the date_range_by_week function. Is there a more efficient way to split up the days by week?