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:
now = Date.today
year = now.year - birth_date.year
if (date+year.year) > now
year = year - 1
end
Is there a more Ruby'ish way to calculate age?
One liner in Ruby on Rails (ActiveSupport). Handles leap years, leap seconds and all.
Logic from here - Calculate age in C#
Assuming both dates are in same timezone, if not call
utc()
beforeto_s()
on both.Because Ruby on Rails is tagged, the dotiw gem overrides the Rails built-in distance_of_times_in_words and provides distance_of_times_in_words_hash which can be used to determine the age. Leap years are handled fine for the years portion although be aware that Feb 29 does have an effect on the days portion that warrants understanding if that level of detail is needed. Also, if you don't like how dotiw changes the format of distance_of_time_in_words, use the :vague option to revert to the original format.
Add dotiw to the Gemfile:
On the command line:
Include the DateHelper in the appropriate model to gain access to distance_of_time_in_words and distance_of_time_in_words_hash. In this example the model is 'User' and the birthday field is 'birthday.
Add this method to that same model.
Usage:
The answers so far are kinda weird. Your original attempt was pretty close to the right way to do this:
You will get a fractional result, so feel free to convert the result to an integer with
to_i
. This is a better solution because it correctly treats the date difference as a time period measured in days (or seconds in the case of the related Time class) since the event. Then a simple division by the number of days in a year gives you the age. When calculating age in years this way, as long as you retain the original DOB value, no allowance needs to be made for leap years.To account for leap years (and assuming activesupport presence):
years_since
will correctly modify the date to take into account non-leap years (when birthday is02-29
).