I\'d like to get a person\'s age from its birthday. now - birthday / 365
doesn\'t work, because some years have 366 days. I came up with the following code:
I think it's alot better to do not count months, because you can get exact day of a year by using Time.zone.now.yday
.
def age
years = Time.zone.now.year - birthday.year
y_days = Time.zone.now.yday - birthday.yday
y_days < 0 ? years - 1 : years
end
I believe this is functionally equivalent to @philnash's answer, but IMO more easily understandable.
class BirthDate
def initialize(birth_date)
@birth_date = birth_date
@now = Time.now.utc.to_date
end
def time_ago_in_years
if today_is_before_birthday_in_same_year?
age_based_on_years - 1
else
age_based_on_years
end
end
private
def age_based_on_years
@now.year - @birth_date.year
end
def today_is_before_birthday_in_same_year?
(@now.month < @birth_date.month) || ((@now.month == @birth_date.month) && (@now.day < @birth_date.day))
end
end
Usage:
> BirthDate.new(Date.parse('1988-02-29')).time_ago_in_years
=> 31
Came up with a Rails variation of this solution
def age(dob)
now = Date.today
age = now.year - dob.year
age -= 1 if dob > now.years_ago(age)
age
end
I've found this solution to work well and be readable for other people:
age = Date.today.year - birthday.year
age -= 1 if Date.today < birthday + age.years #for days before birthday
Easy and you don't need to worry about handling leap year and such.
My suggestion:
def age(birthday)
((Time.now - birthday.to_time)/(60*60*24*365)).floor
end
The trick is that the minus operation with Time returns seconds
This answer is the best, upvote it instead.
I like @philnash's solution, but the conditional could be compacter. What that boolean expression does is comparing [month, day] pairs using lexicographic order, so one could just use ruby's string comparison instead:
def age(dob)
now = Date.today
now.year - dob.year - (now.strftime('%m%d') < dob.strftime('%m%d') ? 1 : 0)
end