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

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

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

 Jack is  old. 

产量

 Jack is over 59 years old. 

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

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

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

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

 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) 
 require 'date' def years_since(dt) delta = (Date.today - Date.parse(dt)) / 365 delta.to_i end 

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

处理闰年的方法

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

 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 

与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 

你可以使用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 

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

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

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

 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年是闰年而生日是在闰日附近。

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

这个怎么样:

 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 

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

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

怎么样的:

 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 

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