Get person's age in Ruby

前端 未结 24 2778
忘了有多久
忘了有多久 2020-11-27 10:32

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:

相关标签:
24条回答
  • 2020-11-27 10:54

    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
    
    0 讨论(0)
  • 2020-11-27 10:56

    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 
    
    0 讨论(0)
  • 2020-11-27 10:56

    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
    
    0 讨论(0)
  • 2020-11-27 10:57

    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.

    0 讨论(0)
  • 2020-11-27 10:58

    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

    0 讨论(0)
  • 2020-11-27 10:59

    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
    
    0 讨论(0)
提交回复
热议问题