您在Rails中的相对时间如何?


220

我正在编写一个Rails应用程序,但似乎找不到相对时间的方法,即如果给定某个Time类,它可以计算“ 30秒前”或“ 2天前”,或者它的时间超过一个月“ 2008年9月1日”等


1
“计算”似乎是错误的单词,您的意思是“输出”吗?
lulalala

Answers:


366

听起来好像您正在从ActiveSupport 寻找time_ago_in_words方法(或distance_of_time_in_words)。这样称呼它:

<%= time_ago_in_words(timestamp) %>

4
提示如何在irb中运行红宝石新手?我运行:需要'active_support',然后尝试'time_ago_in_words(Time.now)',但是找不到该函数。
cboettig 2012年

2
@cboettig不是它的一部分ActiveSupport,它在中定义ActionView::Helpers::DateHelper
迈克尔·科尔

19
如果您在Rails控制台中,则不需要“ active_support”。有一个称为的控制台方法helper,您可以调用和访问这些方法。 helper.time_ago_in_words(timestamp)
马特·波利托

2
只是,如果您想在irb或纯Ruby中使用它,只需执行以下操作: require 'active_support/core_ext' 首先,然后就可以使用7.days.ago和其他类似的构造了。
likethesky

1
大!我刚来这里是期望一些示例代码并找到了它。我喜欢红宝石和护栏
Marcelo Biffara 2013年

53

我已经写了这个,但是必须检查提到的现有方法,看看它们是否更好。

module PrettyDate
  def to_pretty
    a = (Time.now-self).to_i

    case a
      when 0 then 'just now'
      when 1 then 'a second ago'
      when 2..59 then a.to_s+' seconds ago' 
      when 60..119 then 'a minute ago' #120 = 2 minutes
      when 120..3540 then (a/60).to_i.to_s+' minutes ago'
      when 3541..7100 then 'an hour ago' # 3600 = 1 hour
      when 7101..82800 then ((a+99)/3600).to_i.to_s+' hours ago' 
      when 82801..172000 then 'a day ago' # 86400 = 1 day
      when 172001..518400 then ((a+800)/(60*60*24)).to_i.to_s+' days ago'
      when 518400..1036800 then 'a week ago'
      else ((a+180000)/(60*60*24*7)).to_i.to_s+' weeks ago'
    end
  end
end

Time.send :include, PrettyDate

1
哼,我先读了红宝石,而红宝石没有现成的ActiveSupport。因此,我认为该帖子更具吸引力。但是,在实际问题中,提到了滑轨。
琼克

Rails是一个Web框架,底层语言是ruby。因此,在Rails问题上获取一些红宝石代码是正常的。即使标准红宝石不包括ActiveRecord,仅“ gem install activerecord”命令也支持它。
MickaelFM,2009年

7
您可以将最后return一行放在case下方的语句中else,并删除所有return
萨瓦

2
有人能告诉我为什么+99 +800 +180000吗?
Gaurav Shah 2012年

+99,因为“一个小时前”的结尾在7100处结束,这比两个小时少100秒。同样,+ 800,因为172000比两天(172800秒)还短800秒,依此类推。
Fred

22

只是为了阐明Andrew Marshall使用time_ago_in_words 的解决方案
(对于Rails 3.0和Rails 4.0)

如果您在视野中

<%= time_ago_in_words(Date.today - 1) %>

如果您在控制器中

include ActionView::Helpers::DateHelper
def index
  @sexy_date = time_ago_in_words(Date.today - 1)
end

控制器默认没有导入ActionView :: Helpers :: DateHelper模块。

注意:将帮助程序导入控制器不是“正确的方法”。助手用于帮助视图。将time_ago_in_words方法确定为MVC三元组中的视图实体。(我不同意,但在罗马时...)


20

关于什么

30.seconds.ago
2.days.ago

还是您要拍摄的其他东西?


19
这与问题的陈述是相反的。
xaxxon 2011年


10

这样的事情会起作用。

def relative_time(start_time)
  diff_seconds = Time.now - start_time
  case diff_seconds
    when 0 .. 59
      puts "#{diff_seconds} seconds ago"
    when 60 .. (3600-1)
      puts "#{diff_seconds/60} minutes ago"
    when 3600 .. (3600*24-1)
      puts "#{diff_seconds/3600} hours ago"
    when (3600*24) .. (3600*24*30) 
      puts "#{diff_seconds/(3600*24)} days ago"
    else
      puts start_time.strftime("%m/%d/%Y")
  end
end

11
这实质上是distance_of_time_in_words帮手的重新实现:api.rubyonrails.com/classes/ActionView/Helpers/...
格兰特哈钦斯

2
这意味着您不应该使用它,而应该使用内置的
xaxxon,2011年

对我来说,这似乎完全可以。它允许您自定义其余的字符串。即“ 3秒前”与“ 3秒前”
raidfive 2012年

#{diff_seconds/360}应该是#{diff_seconds/3600}。我已经编辑了
Femaref

7

由于这里的答案最多,建议使用time_ago_in_words

而不是使用:

<%= time_ago_in_words(comment.created_at) %>

在Rails中,首选:

<abbr class="timeago" title="<%= comment.created_at.getutc.iso8601 %>">
  <%= comment.created_at.to_s %>
</abbr>

以及一个jQuery库http://timeago.yarp.com/,代码为:

$("abbr.timeago").timeago();

主要优点:缓存

http://rails-bestpractices.com/posts/2012/02/10/not-use-time_ago_in_words/


1
实际上,现在time_ago_in_words不是时间S
23tux

6

在这里看看实例方法:

http://apidock.com/rails/时间

这具有有用的方法,例如昨天,明天,周初,前等。

例子:

Time.now.yesterday
Time.now.ago(2.days).end_of_day
Time.now.next_month.beginning_of_month


1

如果要构建Rails应用程序,则应使用

Time.zone.now
Time.zone.today
Time.zone.yesterday

这样可以在配置Rails应用程序的时区中提供时间或日期。

例如,如果您将应用程序配置为使用UTC,则 Time.zone.now则将始终处于UTC时间(例如,不会受到英国夏令时的更改的影响)。

计算相对时间很容易,例如

Time.zone.now - 10.minute
Time.zone.today.days_ago(5)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.