Ruby age method with date of birth, including months

I have a method in my user model to calculate the age of the user and return the string read by the user. My user can be from 1 month and up, so the returned string differs depending on whether the person is “2 months” or “1 year” or “2 years and 3 months”.

I reviewed a few SO posts to come to this solution. Is there something I can't see? Leap years? Thank!

def age
    dob = self.date_of_birth

    # if a date of birth is not nil
    if dob != nil 

      # get current date  
      now = Date.current

      # has person had their birthday yet this year
      had_birthday = ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? true : false) 

      # if yes then subtract this year from birthday year, if not then also subtract 1 to get how many full years old they are
      years = now.year - dob.year - (had_birthday ? 0 : 1)

      # get the calendar month difference from birthdya calendar month and today calendar month.  if they have not had their birthdya yet then subtract the difference from 12
      months = had_birthday ? now.month - dob.month : 12 - (now.month - dob.month)

      # for under 1 year olds
      if years == 0
        return months > 1 ? months.to_s + " months old" : months.to_s + " month old"  

      # for 1 year olds
      elsif years == 1
        return months > 1 ? years.to_s + " year and " + months.to_s + " months old" : years.to_s + " year and " + months.to_s + " month old" 

      # for older than 1
      else
        return months > 1 ? years.to_s + " years and " + months.to_s + " months old" : years.to_s + " years and " + months.to_s + " month old"
      end

    # No date of birth saved so can not calculate age
    else
      return "No Date of Birth"
    end
  end
+4
source share
4 answers

codereview, .

, .

-, , .

def readable_age(years, months)
  # for under 1 year olds
  if years == 0
    return months > 1 ? months.to_s + " months old" : months.to_s + " month old"  

  # for 1 year olds
  elsif years == 1
    return months > 1 ? years.to_s + " year and " + months.to_s + " months old" : years.to_s + " year and " + months.to_s + " month old" 

  # for older than 1
  else
    return months > 1 ? years.to_s + " years and " + months.to_s + " months old" : years.to_s + " years and " + months.to_s + " month old"
  end
end

, , actionview, pluralize. -

def readable_age(years, months)
  year_text = ''
  if years == 0
    year_text = "#{years} #{pluralize('year', years)} and "
  end

  "#{year_text}#{pluralize('month', months)} old"
end

.

def age(t)
  dob = self.date_of_birth

  months = (t.year * 12 + t.month) - (dob.year * 12 + dob.month)

  # months / 12 will give the number of years
  # months % 12 will give the number of months
  readable_age(months / 12, 15 % 12)
end

, age, . , .

+5

time_ago_in_words:

Class.new.extend(ActionView::Helpers::DateHelper).time_ago_in_words(Time.parse("1981-11-20"))
=> "over 34 years"

: , , . , .

+4

Another option based on the Rational class and some date calculations supported by Rails.

def age
  return 'No Date of Birth' unless date_of_birth.present?

  days_alive = Date.now - date_of_birth
  years = (days_alive / 365).to_i
  months = ((days_alive % 365) / 30).to_i
  [pluralized(years, 'year'), pluralized(months, 'month')].compact.join(' ')
end

def pluralized(quantity, noun)
  return nil if quantity.zero?
  return noun.singularize if quantity == 1
  noun.pluralize
end
+1
source

Using Rails Helpers:

DateHelper = Class.new.extend(ActionView::Helpers::DateHelper)
DateHelper.time_ago_in_words(Time.parse("2002-02-20"))
=> "almost 15 years"

http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html#method-i-time_ago_in_words

0
source

All Articles