Get person's age in Ruby

2020-01-24 19:08发布

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?

24条回答
虎瘦雄心在
2楼-- · 2020-01-24 19:45

This is a conversion of this answer (it's received a lot of votes):

# convert dates to yyyymmdd format
today = (Date.current.year * 100 + Date.current.month) * 100 + Date.today.day
dob = (dob.year * 100 + dob.month) * 100 + dob.day
# NOTE: could also use `.strftime('%Y%m%d').to_i`

# convert to age in years
years_old = (today - dob) / 10000

It's definitely unique in its approach but makes perfect sense when you realise what it does:

today = 20140702 # 2 July 2014

# person born this time last year is a 1 year old
years = (today - 20130702) / 10000

# person born a year ago tomorrow is still only 0 years old
years = (today - 20130703) / 10000

# person born today is 0
years = (today - 20140702) / 10000  # person born today is 0 years old

# person born in a leap year (eg. 1984) comparing with non-leap year
years = (20140228 - 19840229) / 10000 # 29 - a full year hasn't yet elapsed even though some leap year babies think it has, technically this is the last day of the previous year
years = (20140301 - 19840229) / 10000 # 30

# person born in a leap year (eg. 1984) comparing with leap year (eg. 2016)
years = (20160229 - 19840229) / 10000 # 32
查看更多
何必那么认真
3楼-- · 2020-01-24 19:45

The following seems to work (but I'd appreciate it if it was checked).

age = now.year - bday.year
age -= 1 if now.to_a[7] < bday.to_a[7]
查看更多
\"骚年 ilove
4楼-- · 2020-01-24 19:46

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
查看更多
Anthone
5楼-- · 2020-01-24 19:47

Here's my solution which also allows calculating the age at a specific date:

def age on = Date.today
  (_ = on.year - birthday.year) - (on < birthday.since(_.years) ? 1 : 0)
end
查看更多
爱情/是我丢掉的垃圾
6楼-- · 2020-01-24 19:49

Ok what about this:

def age
  return unless dob
  t = Date.today
  age = t.year - dob.year
  b4bday = t.strftime('%m%d') < dob.strftime('%m%d')
  age - (b4bday ? 1 : 0)
end

This is assuming we are using rails, calling the age method on a model, and the model has a date database column dob. This is different from other answers because this method uses strings to determine if we are before this year's birthday.

For example, if dob is 2004/2/28 and today is 2014/2/28, age will be 2014 - 2004 or 10. The floats will be 0228 and 0229. b4bday will be "0228" < "0229" or true. Finally, we will subtract 1 from age and get 9.

This would be the normal way to compare the two times.

def age
  return unless dob
  t = Date.today
  age = today.year - dob.year
  b4bday = Date.new(2016, t.month, t.day) < Date.new(2016, dob.month, dob.day)
  age - (b4bday ? 1 : 0)
end

This works the same, but the b4bday line is too long. The 2016 year is also unnecessary. The string comparison at the beginning was the result.

You can also do this

Date::DATE_FORMATS[:md] = '%m%d'

def age
  return unless dob
  t = Date.today
  age = t.year - dob.year
  b4bday = t.to_s(:md) < dob.to_s(:md)
  age - (b4bday ? 1 : 0)
end

If you aren't using rails, try this

def age(dob)
  t = Time.now
  age = t.year - dob.year
  b4bday = t.strftime('%m%d') < dob.strftime('%m%d')
  age - (b4bday ? 1 : 0)
end

查看更多
我想做一个坏孩纸
7楼-- · 2020-01-24 19:50

If you don't care about a day or two, this would be shorter and pretty self-explanitory.

(Time.now - Time.gm(1986, 1, 27).to_i).year - 1970
查看更多
登录 后发表回答