Skip to content

Instantly share code, notes, and snippets.

@woods
Created April 17, 2009 18:20
Show Gist options
  • Save woods/97172 to your computer and use it in GitHub Desktop.
Save woods/97172 to your computer and use it in GitHub Desktop.
# Return as a three-element array the number of years, months, and days
# between the two given dates.
#
# Time is counted from the "from" date, in the order of years,
# months, and days. This order is significant since leap years will
# pass unnoticed if they are "absorbed" by a year or month
# calculation. For example, 2007 to 2008 is a year and February 15th
# to March 15th is a month, whether they include a leap day or not.
# However, the leap year is observed properly if it occurs within the
# days portion of the calculation. For example February 20th to March
# 3rd may be 12 or 11 days, depending on whether it's a leap year.
def age(from_date, to_date)
return nil if from_date.nil? || to_date.nil?
from, to = from_date, to_date.dup
age_years = to.year - from.year
# Carry a year?
if from.month > to.month
age_years -= 1
carry_months = 12
else
carry_months = 0
end
age_months = to.month + carry_months - from.month
# Carry a month?
if from.day > to.day
age_months -= 1
if age_months < 0
# carry again
age_years -= 1
age_months += 12
end
# Carry the number of days in the month before the "to" month
carry_days = Time.days_in_month(to.last_month.month, to.last_month.year)
else
carry_days = 0
end
age_days = to.day + carry_days - from.day
[age_years, age_months, age_days]
end
# Return the chronological age of the subject at the time of the test's
# administration as a 2-element array of years and months.
#
# If the day component of the subject's age is more than 15 days, then the
# month is rounded upwards.
def chronological_age
return nil if subject.nil? || subject.date_of_birth.nil? || date_of_administration.nil?
age_years, age_months, age_days = age(subject.date_of_birth, date_of_administration)
# Round up if they're more than halfway through the month.
if age_days > 15
if age_months == 11
age_years += 1
age_months = 0
else
age_months += 1
end
end
[age_years, age_months]
end
# Like #chronological_age, but return the result as an integer of total
# months.
def chronological_age_in_months
years, months = chronological_age
if years.nil? || months.nil?
nil
else
(years * 12) + months
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment