This question was here for other languages, so let here be one for Ruby.
How do I calculate number of complete years that have passed from a given date? As you prob
require 'date'
def years_since(dt)
delta = (Date.today - Date.parse(dt)) / 365
delta.to_i
end
Do you want age as people typically understand it, or are you looking for a precise measure of time elapsed? If the former, there is no need to worry about leap years and other complications. You simply need to compute a difference in years and reduce it if the person has not had a birthday yet this year. If the latter, you can convert seconds elapsed into years, as other answers have suggested.
def age_in_completed_years (bd, d)
# Difference in years, less one if you have not had a birthday this year.
a = d.year - bd.year
a = a - 1 if (
bd.month > d.month or
(bd.month >= d.month and bd.day > d.day)
)
a
end
birthdate = Date.new(2000, 12, 15)
today = Date.new(2009, 12, 14)
puts age_in_completed_years(birthdate, today)
I came up with the following, based on a similar reasoning as @FMc
First, compute the diff between today's year and birthday's year. Then, sum it to birthday and check the resulting date: if it's greater than today, decrease diff by 1.
To be used in Rails apps as it relies on ActiveSupport
's years
method
def age(birthday, today)
diff = today.year - birthday.year
(birthday + diff.years > today ) ? (diff - 1) : diff
end
Same idea as FM but with a simplified if statement. Obviously, you could add a second argument instead of using current time.
def age(birthdate)
now = DateTime.now
age = now.year - birthdate.year
age -= 1 if(now.yday < birthdate.yday)
age
end
I think this will always work, even for someone with a birthday near a leap day:
require 'date'
def calculate_age(start_date, end_date)
end_date.year - start_date.year - ((end_date.month > start_date.month || (end_date.month == start_date.month && end_date.day >= start_date.day)) ? 0 : 1)
end
puts calculate_age( Date.strptime('03/02/1968', '%m/%d/%Y'), Date.strptime('03/02/2010', '%m/%d/%Y'))
The calculated age with this method in the example call above is 42, which is correct despite 1968 being a leap year and the birthday being near a leap day.
Plus, this way there is no need to create a local variable.
I have a gem/plugin called dotiw that has a distance_of_time_in_words_hash
that will return a hash like: { :years => 59, :months => 11, :days => 27 }
. From that you could work out if it's near a certain limit.