在Rails中,用英语显示两个日期之间的时间

在Rails项目中,我想找到两个日期之间的差异,然后用自然语言显示它。 就像是

>> (date1 - date2).to_natural_language "3 years, 2 months, 1 week, 6 days" 

基本上这是ruby。

谷歌和Rails API没有发现任何东西。 我发现了一些可以让你在一个单元中产生差异的东西(即两个日期之间有多少个星期)但不能准确计算出几年,几个月,几周,几天的东西。

其他答案可能不会给出您正在寻找的输出类型,因为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) end end components.join(", ") end 

然后在一个视图中你可以说:

 <%= time_diff_in_natural_language(Time.now, 2.5.years.ago) %> => 2 years, 6 months, 2 days 

给定的方法仅限于几天,但如果需要,可以很容易地扩展为添加更小的单位。

Rails的ActionView模块包括两种ActionView您需求的方法:

  • distance_of_time_in_words
  • distance_of_time_in_words_to_now

我尝试了Daniel的解决方案 ,发现一些测试用例的结果不正确,因为它没有正确处理几个月内发现的可变天数:

  > 30.days <1.month
    =>假

所以,例如:

  > d1 = DateTime.civil(2011,4,4)
 > d2 = d1 + 1.year + 5.months
 > time_diff_in_natural_language(d1,d2)
 >“1年,5个月,3天” 

以下内容将为您提供{年,月,日,小时,分钟,秒}的正确数量:

  def time_diff(from_time,to_time)
   %w(年月日小时分秒).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如果from_time + delta.send(interval)> to_time
     from_time + = delta.send(interval)
    三角洲
  结束
结束
 > time_diff(d1,d2)
  => [1,5,0,0,0,0] 

distance_of_time_in_words在这里是最准确的。 丹尼尔的答案是错误的:2。5年前,应该产生2年零6个月。 问题是,月份包含28-31天,而年份可能会飞跃。

我希望我知道如何解决这个问题:(

DateHelper#distance_of_time_in_words

 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