From: Nando Sanchez Date: 2007-03-16T16:17:55+09:00 Subject: Re: Calculating the age given DOB Very nice piece of code Rick! I'm a Ruby newbee and I find it facinating when I see code that applies better the "Ruby Way". Thanks for sharing. I borrow parts of your code and rewrote the method I sent: class Date def elapsedYearsAndDays(rangeDate) startDate, endDate = *(self >= rangeDate ? [rangeDate, self] : [self, rangeDate]) #This is the real problem: Febraury 29th! isMagicDate = (startDate.month == 2) && (startDate.day == 29) startDate += 1 if !endDate.leap? && isMagicDate elapsedYears = endDate.year - startDate.year previousStartDate = Date.new(endDate.year, startDate.month, startDate.day) if endDate < previousStartDate elapsedYears -= 1 previousStartDate = Date.new(endDate.year - 1, startDate.month, startDate.day) previousStartDate -= 1 if previousStartDate.leap? && isMagicDate end return elapsedYears, endDate - previousStartDate end end startDates = [Date.today, Date.new(1963, 11, 22), Date.new(2007, 3, 1), Date.new(2004, 3, 1), Date.new(2004, 2, 29), Date.new(2004, 3, 1), Date.new(2004, 2, 29), Date.new(2007,3,15), Date.new(2000,3,14)] endDates = [Date.new(1963, 11, 22), Date.new(1963, 11, 22), Date.new(2004, 3, 1), Date.new(2001, 3, 2), Date.new(2001, 3, 1), Date.new(2001, 3, 1), Date.new(2009, 3, 1), Date.new(2000,3,14), Date.new(2007,3,15)] startDates.each_with_index do |startDate, index| elapsedYears, elapsedDays = startDate.elapsedYearsAndDays(endDates[index]) daysMessage = (elapsedDays > 0) ? (" and #{elapsedDays} day(s)") : '' puts "Start date: #{startDate} End date: #{endDates[index]}" puts "Elapsed time: #{elapsedYears} year(s)#{daysMessage}\n\n" end =begin --------------------------------------------------------------------------- At the same time I took your code and added the same test dates I used: =end require 'date' class Date # return the number of days since the beginning of the year def years_since(date) # The parens in the expression below aren't strictly necessary, but # I think it makes what's going on a little bit clearer. first, last = *(self >= date ? [date, self] : [self, date]) (self <=> date) * ((last.year - first.year) - (first.yday > last.yday ? 1 : 0)) end end startDates = [Date.today, Date.new(1963, 11, 22), Date.new(2007, 3, 1), Date.new(2004, 3, 1), Date.new(2004, 2, 29), Date.new(2004, 3, 1), Date.new(2004, 2, 29), Date.new(2007,3,15), Date.new(2000,3,14)] endDates = [Date.new(1963, 11, 22), Date.new(1963, 11, 22), Date.new(2004, 3, 1), Date.new(2001, 3, 2), Date.new(2001, 3, 1), Date.new(2001, 3, 1), Date.new(2009, 3, 1), Date.new(2000,3,14), Date.new(2007,3,15)] startDates.each_with_index do |startDate, index| elapsedYears = startDate.years_since(endDates[index]) puts "Start date: #{startDate} End date: #{endDates[index]}" puts "Elapsed time: #{elapsedYears} year(s)\n\n" end =begin As you can see from the results, both pieces of code give the same results except when a leap year is involved. I think my version is correct in those cases :) because we don't want to say that a complete year has passed until that is totally true. Regards, Nando =end -- Posted via http://www.ruby-forum.com/.