代码之家  ›  专栏  ›  技术社区  ›  P Shved

在Ruby中,如何计算自给定日期以来经过了多少年?

  •  18
  • P Shved  · 技术社区  · 15 年前

    这个问题是针对其他语言的,所以让我们来看看Ruby。

    如何计算从给定日期算起的完整年份数?正如你可能已经猜到的,这是自动计算人的年龄。最近的是 distance_of_time_in_words Rails助手,所以下面的模板

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

    产量

    Jack is over 59 years old.
    

    但我需要更精确的函数,它只产生数字。有吗?

    如果存在某种RubyonRails帮助函数,这是可以的,尽管纯Ruby解决方案会更好。

    编辑:问题的要点是需要一个非近似的解决方案。在2 三月份的杰克应该59岁,第二天他应该60岁。应考虑闰年等因素。

    12 回复  |  直到 7 年前
        1
  •  39
  •   FMc TLP    15 年前

    你想要人们通常理解的年龄,还是你在寻找一个精确的时间度量?如果是前者,就不必担心闰年等并发症。如果这个人今年还没有过生日,你只需要计算年内的差额,并将其减少。如果是后者,您可以将经过的秒数转换为年数,正如其他答案所建议的那样。

    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)
    
        2
  •  5
  •   sh-beta    15 年前
    require 'date'
    
    def years_since(dt)
        delta = (Date.today - Date.parse(dt)) / 365
        delta.to_i
    end
    
        3
  •  5
  •   Ryan Bigg Andrés Bonilla    15 年前

    我有一个gem/plugin叫做 dotiw 那有 distance_of_time_in_words_hash 它将返回一个散列,比如: { :years => 59, :months => 11, :days => 27 } . 如果接近某个极限,你就可以从中得出结论。

        4
  •  4
  •   Nathan Long    12 年前

    处理闰年的方法

    每当你计算一个日期之后经过的年份时,你必须决定如何处理闰年。这是我的方法,我认为它非常易读,并且能够在不使用任何“特殊情况”逻辑的情况下大踏步前进。

    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
    
        5
  •  2
  •   lda    14 年前

    威辛 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
    
        6
  •  2
  •   Raj Adroit    11 年前

    你可以用红宝石 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
    
        7
  •  2
  •   Davide Papagni    7 年前

    基于与@fmc相似的推理,我得出了以下结论 首先,计算今天一年和生日一年的差额。然后,将其和到生日并检查结果日期:如果大于今天,则将diff减少1。 在Rails应用程序中使用,因为它依赖 ActiveSupport years 方法

    def age(birthday, today)
      diff = today.year - birthday.year
      (birthday + diff.years > today ) ? (diff - 1) : diff
    end
    
        8
  •  1
  •   dingo sky    15 年前

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

    def age(birthdate)
      now = DateTime.now
      age = now.year - birthdate.year
      age -= 1 if(now.yday < birthdate.yday)
      age
    end
    
        9
  •  1
  •   Glenn    15 年前

    我认为这总是有效的,即使对于一个在闰日附近过生日的人:

    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年是闰年,生日接近闰日。

    另外,这样就不需要创建局部变量。

        10
  •  1
  •   Jason Waldrip    12 年前

    这个怎么样?

    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
    
        11
  •  0
  •   khelll    15 年前

    比如:

    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
    
        12
  •  0
  •   Ken Herbert    11 年前

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