views:

739

answers:

3

I am trying to create a page to display a list of links for each month, grouped into years. The months need to be between two dates, Today, and The date of the first entry.

I am at a brick wall, I have no idea how to create this.

Any help would be massively appriciated

Regards Adam

A: 

I don't know if I've completely understood your problem, but some of the following might be useful. I've taken advantage of the extensions to Date provided in ActiveSupport:

d1 = Date.parse("20070617") # => Sun, 17 Jun 2007
d2 = Date.parse("20090529") #=> Fri, 29 May 2009
eom = d1.end_of_month #=> Sat, 30 Jun 2007
mth_ends = [eom] #=> [Sat, 30 Jun 2007]
while eom < d2
  eom = eom.advance(:days => 1).end_of_month
  mth_ends << eom
end
yrs = mth_ends.group_by{|me| me.year}

The final line uses another handy extension: Array#group_by, which does pretty much exactly what it promises.

d1.year.upto(d2.year) do |yr|
  puts "#{yrs[yr].min}, #{yrs[yr].max}"
end
2007-06-30, 2007-12-31
2008-01-31, 2008-12-31
2009-01-31, 2009-05-31

I don't know if the start/end points are as desired, but you should be able to figure out what else you might need.

HTH

Mike Woodhouse
A: 

The following code will add a months_between instance method to the Date class

#!/usr/bin/ruby 

require 'date'

class Date

  def self.months_between(d1, d2)
    months = []
    start_date = Date.civil(d1.year, d1.month, 1)
    end_date = Date.civil(d2.year, d2.month, 1)

    raise ArgumentError unless d1 <= d2

    while (start_date < end_date)
      months << start_date
      start_date = start_date >>1
    end

    months << end_date

  end
end

This is VERY lightly tested, however it returns an Array of dates each date being the 1st day in each affected month.

Steve Weet
+8  A: 

Just put what you want inside a range loop and use the Date::MONTHNAMES array like so

(date.year..laterdate.year).each do |y|
   mo_start = (date.year == y) ? date.month : 1
   mo_end = (laterdate.year == y) ? laterdate.month : 12

   (mo_start..mo_end).each do |m|  
       puts Date::MONTHNAMES[m]
   end
end
ErsatzRyan
Need to add an outer loop for years
marcumka
Yeah i just noticed that, edited should work now
ErsatzRyan
+1 Nice, but needs to be modified to show the year, as per the original requirement
Steve Weet
Thanks guys, that's done it! You heroes!
@Steve - Yeah I didn't care so much about the presentation just showing him an easy way to do the iteration, let him do what he wants inside the loops
ErsatzRyan