Ruby-on-rails 在 Rails 中,用英文显示两个日期之间的时间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1065320/
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
In Rails, display time between two dates in English
提问by Eric Wright
In a Rails project I want to find the difference between two dates and then display it in natural language. Something like
在 Rails 项目中,我想找到两个日期之间的差异,然后以自然语言显示。就像是
>> (date1 - date2).to_natural_language
"3 years, 2 months, 1 week, 6 days"
Basically thisfor ruby.
基本上这是红宝石。
Google and the Rails API haven't turned up anything. I've found some things that will give you the difference in one unit (ie, how many weeks between two dates) but not something that will accurately calculate years, months, weeks, days all together.
Google 和 Rails API 没有发现任何东西。我发现有些东西可以给你一个单位的差异(即,两个日期之间有多少周),但不能准确计算年、月、周、天。
回答by John Topley
The Rails' ActionViewmodule includes two methods that may do what you require:
Rails 的ActionView模块包括两种方法,可以满足您的要求:
回答by Daniel Vandersluis
The other answers may not give the type of output that you're looking for, because instead of giving a string of years, months, etc., the Rails helpers just show the largest unit. If you're looking for something more broken down, here's another option. Stick this method into a helper:
其他答案可能不会给出您正在寻找的输出类型,因为 Rails 助手不会给出一连串的年、月等信息,而是只显示最大的单位。如果您正在寻找更细分的东西,这里有另一种选择。将此方法粘贴到帮助程序中:
def time_diff_in_natural_language(from_time, to_time)
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
distance_in_seconds = ((to_time - from_time).abs).round
components = []
%w(year month week day).each do |interval|
# For each interval type, if the amount of time remaining is greater than
# one unit, calculate how many units fit into the remaining time.
if distance_in_seconds >= 1.send(interval)
delta = (distance_in_seconds / 1.send(interval)).floor
distance_in_seconds -= delta.send(interval)
components << pluralize(delta, interval)
# if above line give pain. try below one
# components << interval.pluralize(delta)
end
end
components.join(", ")
end
And then in a view you can say something like:
然后在视图中你可以这样说:
<%= time_diff_in_natural_language(Time.now, 2.5.years.ago) %>
=> 2 years, 6 months, 2 days
The given method only goes down to days, but can be easily extended to add in smaller units if desired.
给定的方法只能缩短到几天,但如果需要,可以轻松扩展以添加更小的单位。
回答by klochner
I tried Daniel's solutionand found some incorrect results for a few test cases, due to the fact that it doesn't correctly handle the variable number of days found in months:
我尝试了Daniel 的解决方案,发现一些测试用例的结果不正确,因为它没有正确处理几个月内发现的可变天数:
> 30.days < 1.month
=> false
So, for example:
因此,例如:
> d1 = DateTime.civil(2011,4,4)
> d2 = d1 + 1.year + 5.months
> time_diff_in_natural_language(d1,d2)
=> "1 year, 5 months, 3 days" The following will give you the correct number of {years,months,days,hours,minutes,seconds}:
以下将为您提供正确的 {years,months,days,hours,minutes,seconds} 数:
def time_diff(from_time, to_time)
%w(year month day hour minute second).map do |interval|
distance_in_seconds = (to_time.to_i - from_time.to_i).round(1)
delta = (distance_in_seconds / 1.send(interval)).floor
delta -= 1 if from_time + delta.send(interval) > to_time
from_time += delta.send(interval)
delta
end
end
> time_diff(d1,d2)
=> [1, 5, 0, 0, 0, 0] 回答by Anton
distance_of_time_in_wordsis the most accurate here. Daniel's answer is actully wrong: 2.5 years ago should produce exactly 2 years, 6 months. The issue is that months contain 28-31 day, and years might be leap.
distance_of_time_in_words这里是最准确的。Daniel 的回答实际上是错误的:2.5 年前应该正好是 2 年零 6 个月。问题是月份包含 28-31 天,而年份可能是闰年。
I wish I knew how to fix this :(
我希望我知道如何解决这个问题:(
回答by Роман Хребтов
def date_diff_in_natural_language(date_from, date_to)
components = []
%w(years months days).each do |interval_name|
interval = 1.send(interval_name)
count_intervals = 0
while date_from + interval <= date_to
date_from += interval
count_intervals += 1
end
components << pluralize(count_intervals, interval_name) if count_intervals > 0
end
components.join(', ')
end

