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

时间:2009-12-14 22:56:00

标签: ruby-on-rails ruby datetime

这个问题出现在其他语言中,所以让我们来看看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.

但我需要更精确的功能才能产生数字。有吗?

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

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

13 个答案:

答案 0 :(得分:39)

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

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)

答案 1 :(得分:5)

require 'date'

def years_since(dt)
    delta = (Date.today - Date.parse(dt)) / 365
    delta.to_i
end

答案 2 :(得分:5)

我有一个名为dotiw的gem /插件,其distance_of_time_in_words_hash将返回类似:{ :years => 59, :months => 11, :days => 27 }的哈希值。如果它接近一定限度,你可以解决这个问题。

答案 3 :(得分:4)

处理闰年的方法

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

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 :(得分:3)

基于与@FMc类似的推理,我提出了以下内容 首先,计算今天和生日之间的差异。然后,将它加到生日并检查结果日期:如果它大于今天,则减少差异1。 要在Rails应用中使用,因为它依赖于ActiveSupport的{​​{1}}方法

years

答案 5 :(得分:2)

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)

你可以使用ruby gem 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 :(得分:1)

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

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

答案 8 :(得分:1)

我认为即使对于在闰日附近过生日的人,这也会一直有效:

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年是闰年且生日接近闰日,但这是正确的。

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

答案 9 :(得分: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

答案 10 :(得分:0)

如下:

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

答案 11 :(得分:0)

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

答案 12 :(得分:0)

要计算两个日期之间的年和月数,我使用了此功能

  def calculate_year_month(from_date, to_date)
    num_days = (from_date - to_date).to_i
    num_months = (num_days / 30) 
    num_years = (num_months / 12) 
    num_months = (num_months % 12) 
    return num_years.to_s + " year(s) and " + num_months.to_s + " month(s)" 
  end