Created
April 17, 2009 18:20
-
-
Save woods/97172 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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