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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:24:51  来源:igfitidea点击:

In Rails, display time between two dates in English

ruby-on-railsrubytime

提问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