如何计算Ruby中给定日期以来经过了多少年?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1904097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to calculate how many years passed since a given date in Ruby?
提问by P Shved
This question was here for other languages, so let here be one for Ruby.
这个问题适用于其他语言,所以让这里成为 Ruby 的问题。
How do I calculate number of complete years that have passed from a given date? As you probably have guessed, that's to calculate person's age automatically. The closest one is distance_of_time_in_wordsRails helper, so the following template
如何计算从给定日期过去的完整年数?您可能已经猜到了,这是自动计算人的年龄。最接近的是distance_of_time_in_wordsRails helper,所以下面的模板
Hyman is <%= distance_of_time_in_words (Time.now, Time.local(1950,03,22)) %> old.
yields
产量
Hyman is over 59 years old.
But I need more precise function that yields just number. Is there one?
但我需要更精确的函数,只产生数字。有吗?
If there exists some kind of Ruby on Rails helper function for this, this is OK, although pure Ruby solution would be better.
如果为此存在某种 Ruby on Rails 辅助函数,这是可以的,尽管纯 Ruby 解决方案会更好。
Edit: the gist of the question is that a non-approximate solution is needed. At the 2ndof March Hyman should be 59 years old and the next day he should be 60 years old. Leap years and such should be taken into account.
编辑:问题的要点是需要一个非近似的解决方案。在2次三月Hyman的应该是59岁,第二天,他应该是60岁了。闰年等应该考虑在内。
回答by FMc
Do you want age as people typically understand it, or are you looking for a precise measure of time elapsed? If the former, there is no need to worry about leap years and other complications. You simply need to compute a difference in years and reduce it if the person has not had a birthday yet this year. If the latter, you can convert seconds elapsed into years, as other answers have suggested.
您想要人们通常理解的年龄,还是想要精确衡量经过的时间?如果是前者,则无需担心闰年等并发症。如果此人今年还没有过生日,您只需要计算年份差异并减少它。如果是后者,您可以将经过的秒数转换为年数,正如其他答案所建议的那样。
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)
回答by sh-beta
require 'date'
def years_since(dt)
delta = (Date.today - Date.parse(dt)) / 365
delta.to_i
end
回答by Ryan Bigg
I have a gem/plugin called dotiwthat has a distance_of_time_in_words_hashthat will return a hash like: { :years => 59, :months => 11, :days => 27 }. From that you could work out if it's near a certain limit.
我有一个宝石/插件叫做dotiw具有distance_of_time_in_words_hash将返回一个哈希,如:{ :years => 59, :months => 11, :days => 27 }。从那你可以算出它是否接近某个极限。
回答by Nathan Long
An approach that handles leap years
处理闰年的方法
Whenever you're calculating elapsed years since a date, you have to decide how to handle leap year. Here is my approach, which I think is very readable, and is able to take leap years in stride without using any "special case" logic.
每当您计算自某个日期以来经过的年数时,您必须决定如何处理闰年。这是我的方法,我认为它非常易读,并且能够在不使用任何“特殊情况”逻辑的情况下大步跨越闰年。
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
回答by Davide Papagni
I came up with the following, based on a similar reasoning as @FMc
First, compute the diff between today's year and birthday's year. Then, sum it to birthday and check the resulting date: if it's greater than today, decrease diff by 1.
To be used in Rails apps as it relies on ActiveSupport's yearsmethod
基于与@FMc 类似的推理,我想出了以下内容 首先,计算今天年份和生日年份之间的差异。然后,将其与生日相加并检查结果日期:如果它大于今天,则将 diff 减 1。在 Rails 应用程序中使用,因为它依赖于ActiveSupport的years方法
def age(birthday, today)
diff = today.year - birthday.year
(birthday + diff.years > today ) ? (diff - 1) : diff
end
回答by lda
withing http://github.com/radar/dotiw
与http://github.com/radar/dotiw
Hyman is <%= distance_of_time_in_words (Time.now, Time.local(1950,03,22)) %> old.
produce
生产
Hyman is 60 years old
回答by Raj Adroit
you can use the ruby gem adroit-age
你可以使用 ruby gem adroit-age
It works for leap years also..
它也适用于闰年..
age = AdroitAge.find_age("23/01/1990")
Update
更新
require 'adroit-age'
dob = Date.new(1990,1,23)
or
dob = "23/01/1990".to_date
age = dob.find_age
#=> 23
回答by dingo sky
Same idea as FM but with a simplified if statement. Obviously, you could add a second argument instead of using current time.
与 FM 相同的想法,但具有简化的 if 语句。显然,您可以添加第二个参数而不是使用当前时间。
def age(birthdate)
now = DateTime.now
age = now.year - birthdate.year
age -= 1 if(now.yday < birthdate.yday)
age
end
回答by Glenn
I think this will always work, even for someone with a birthday near a leap day:
我认为这将始终有效,即使对于生日接近闰日的人:
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'))
The calculated age with this method in the example call above is 42, which is correct despite 1968 being a leap year and the birthday being near a leap day.
在上面的示例调用中使用此方法计算的年龄是 42,尽管 1968 年是闰年并且生日接近闰日,但这是正确的。
Plus, this way there is no need to create a local variable.
另外,这样就不需要创建局部变量。
回答by Jason Waldrip
How about this:
这个怎么样:
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

