首页 文章

如何计算Ruby中给定日期过去多少年?

提问于
浏览
18

这个问题出现在其他语言中,所以让我们来看看Ruby吧 .

如何计算从给定日期过去的完整年份数?正如您可能已经猜到的那样,'s to calculate person'会自动衰老 . 最接近的是 distance_of_time_in_words Rails helper,所以下面的模板

Jack is <%= distance_of_time_in_words (Time.now, Time.local(1950,03,22)) %> old.

产量

Jack is over 59 years old.

但我需要更精确的功能,只产生数字 . 有吗?

如果存在某种Ruby on Rails辅助函数,这是可以的,尽管纯Ruby解决方案会更好 .

Edit: the gist of the question is that a non-approximate solution is needed. At the 2nd of March Jack should be 59 years old and the next day he should be 60 years old. Leap years and such should be taken into account.

12 回答

  • 5

    您是否想要年龄,因为人们通常会理解它,或者您是否正在寻找精确的时间测量?如果是前者,就没有必要担心闰年等并发症 . 你只需要计算几年的差异,如果这个人今年没有过生日就减少它 . 如果是后者,您可以将经过的秒数转换为年,如其他答案所示 .

    def age_in_completed_years (bd, d)
        # Difference in years, less one if you have not had a birthday this year.
        a = d.year - bd.year
        a = a - 1 if (
             bd.month >  d.month or 
            (bd.month >= d.month and bd.day > d.day)
        )
        a
    end
    
    birthdate = Date.new(2000, 12, 15)
    today     = Date.new(2009, 12, 14)
    
    puts age_in_completed_years(birthdate, today)
    
  • 0

    http://github.com/radar/dotiw

    Jack is <%= distance_of_time_in_words (Time.now, Time.local(1950,03,22)) %> old.
    

    生产环境

    Jack is 60 years old
    
  • 5

    我认为这将永远有效,即使是在闰日附近有生日的人:

    require 'date'
    
    def calculate_age(start_date, end_date)
      end_date.year - start_date.year - ((end_date.month > start_date.month || (end_date.month == start_date.month && end_date.day >= start_date.day)) ? 0 : 1)
    end
    
    puts calculate_age( Date.strptime('03/02/1968', '%m/%d/%Y'), Date.strptime('03/02/2010', '%m/%d/%Y'))
    

    在上面的示例调用中使用此方法计算的年龄是42,这是正确的,尽管1968年是闰年而生日是在闰日附近 .

    另外,这种方式不需要创建局部变量 .

  • 2

    基于与@FMc First类似的推理,我提出了以下内容,计算今天's year and birthday'年之间的差异 . 然后,将它加到生日并检查结果日期:如果它大于今天,将差异减少1.在Rails应用程序中使用,因为它依赖于 ActiveSupportyears 方法

    def age(birthday, today)
      diff = today.year - birthday.year
      (birthday + diff.years > today ) ? (diff - 1) : diff
    end
    
  • 2

    你可以使用红宝石宝石adroit-age

    它适用于闰年也..

    age = AdroitAge.find_age("23/01/1990")
    

    更新

    require 'adroit-age'
    
    dob =  Date.new(1990,1,23)
    or
    dob = "23/01/1990".to_date
    
    age = dob.find_age
    #=> 23
    
  • 0
    require 'date'
    
    def years_since(dt)
        delta = (Date.today - Date.parse(dt)) / 365
        delta.to_i
    end
    
  • 1

    怎么样的:

    def years_diff(from_time,to_time)
      (((to_time - from_time).abs)/ (365 * 24 * 60 * 60)).to_i
    end
    
    years_diff(Time.now,Time.local(1950,03,22)) #=> 59
    years_diff(Time.now,Time.local(2009,03,22)) #=> 0
    years_diff(Time.now,Time.local(2008,03,22)) #=> 1
    
  • 1

    处理闰年的方法

    无论何时计算自某个日期起的经过年限,您都必须决定如何处理闰年 . 这是我的方法,我认为这是非常易读的,并且能够在不使用任何“特殊情况”逻辑的情况下大踏步前进 .

    def years_completed_since(start_date, end_date)
    
      if end_date < start_date
        raise ArgumentError.new(
          "End date supplied (#{end_date}) is before start date (#{start_date})"
        )
      end
    
      years_completed = end_date.year - start_date.year
    
      unless reached_anniversary_in_year_of(start_date, end_date)
        years_completed -= 1
      end
    
      years_completed
    end
    
    # No special logic required for leap day; its anniversary in a non-leap
    # year is considered to have been reached on March 1.
    def reached_anniversary_in_year_of(original_date, new_date)
      if new_date.month == original_date.month
        new_date.day >= original_date.day
      else
        new_date.month > original_date.month
      end
    end
    
  • 4

    与FM相同的想法,但使用简化的if语句 . 显然,您可以添加第二个参数而不是使用当前时间 .

    def age(birthdate)
      now = DateTime.now
      age = now.year - birthdate.year
      age -= 1 if(now.yday < birthdate.yday)
      age
    end
    
  • 1

    这个怎么样:

    def age_in_years(date)
      # Difference in years, less one if you have not had a birthday this year.
      today = Date.today
      age = today.year - date.year
      age = age - 1 if [date.day, date.month, today.year].join('/').to_date > Date.today
    end
    
  • 39

    我有一个名为dotiw的gem /插件,它有一个 distance_of_time_in_words_hash ,它将返回一个像: { :years => 59, :months => 11, :days => 27 } 这样的哈希 . 如果它接近某个限制,你可以解决这个问题 .

  • 1

    d2.year - d1.year - (d2.month > d1.month || (d2.month == d1.month && d2.day >= d1.day) ? 0 : 1)

相关问题