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条回答
Melony?
2楼-- · 2020-01-24 19:28

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
查看更多
男人必须洒脱
3楼-- · 2020-01-24 19:29

Use this:

def age
  now = Time.now.utc.to_date
  now.year - birthday.year - (birthday.to_date.change(:year => now.year) > now ? 1 : 0)
end
查看更多
爷的心禁止访问
4楼-- · 2020-01-24 19:30

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 
查看更多
闹够了就滚
5楼-- · 2020-01-24 19:34

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
查看更多
做自己的国王
6楼-- · 2020-01-24 19:36
  def computed_age
    if birth_date.present?
      current_time.year - birth_date.year - (age_by_bday || check_if_newborn ? 0 : 1)
    else
      age.presence || 0
    end
  end


  private

  def current_time
    Time.now.utc.to_date
  end

  def age_by_bday
    current_time.month > birth_date.month
  end

  def check_if_newborn
    (current_time.month == birth_date.month && current_time.day >= birth_date.day)
  end```
查看更多
该账号已被封号
7楼-- · 2020-01-24 19:39

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.

查看更多
登录 后发表回答