在Ruby中,如何表示发生在“x分钟前”、“x小时前”或“x天前”的事件?

5
如果我在Ruby中有一个时间变量,如何表达它是指以下事件之一:
“x分钟前”或“x小时前”或“x天前”
显然,如果某件事情2天前发生了,我不想说它发生在几分钟前。
4个回答

13

这是一个与语言无关的版本,您应该能够将其转换为任何语言:

ONE_MINUTE = 60
ONE_HOUR = 60 * ONE_MINUTE
ONE_DAY = 24 * ONE_HOUR
ONE_WEEK = 7 * ONE_DAY
ONE_MONTH = ONE_DAY * 3652425 / 120000
ONE_YEAR = ONE_DAY * 3652425 / 10000

def when(then):
    seconds_ago = now() - then

    if seconds_ago < 0:
        return "at some point in the future (???)"
    if seconds_ago == 0:
        return "now"

    if seconds_ago == 1:
        return "1 second ago"
    if seconds_ago < ONE_MINUTE:
        return str(seconds_ago) + " seconds ago"

    if seconds_ago < 2 * ONE_MINUTE:
        return "1 minute ago"
    if seconds_ago < ONE_HOUR:
        return str(seconds_ago/ONE_MINUTE) + " minutes ago"

    if seconds_ago < 2 * ONE_HOUR:
        return "1 hour ago"
    if seconds_ago < ONE_DAY:
        return str(seconds_ago/ONE_HOUR) + " hours ago"

    if seconds_ago < 2 * ONE_DAY:
        return "1 day ago"
    if seconds_ago < ONE_WEEK:
        return str(seconds_ago/ONE_DAY) + " days ago"

    if seconds_ago < 2 * ONE_WEEK:
        return "1 week ago"
    if seconds_ago < ONE_MONTH:
        return str(seconds_ago/ONE_WEEK) + " weeks ago"

    if seconds_ago < 2 * ONE_MONTH:
        return "1 month ago"
    if seconds_ago < ONE_YEAR:
        return str(seconds_ago/ONE_MONTH) + " months ago"

    if seconds_ago < 2 * ONE_YEAR:
        return "1 year ago"
    return str(seconds_ago/ONE_YEAR) + " years ago"
注意,年/月数字是近似值(基于平均值),但这并不重要,因为相对误差仍然非常低。

11

如果您使用的是 Rails:

time_ago_in_words

3
API参考:http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html#M001696 - Josh Lee
2
如果您不是使用Rails,以下是相关方法的源代码:http://dev.rubyonrails.org/browser/trunk/actionpack/lib/action_view/helpers/date_helper.rb?rev=4674#L24 - Josh Lee

0
你需要像这样做:
tnow = Time.now
elapsed = tnow - tevent # elapsed time in seconds

if (elapsed < 60)
  puts "#{elapsed} seconds ago"
elsif (elapsed < 60*60)
  puts "#{elapsed/60} minutes ago"
end

1
哇,我没想到 Ruby 是如此聪明,它能够判断 elapsedepapsed 引用的是同一个变量 :-) - paxdiablo
当别人发布新帖时,我很少编辑它们,我猜想他们会留意并修复它们。如果它保持那样几天,我可能会去编辑。最近的一个例子是一个回答中使用了“gank it off the website”这个短语 - 我认为应该是“yank”,但显然那也是一个单词(尽管可能是俚语)。如果我改变了它,原作者可能会很生气。 - paxdiablo
2
@Pax:'gank' 这个词的解释很好,但在这种情况下,(epapsed 都明显是打错了。 - Telemachus

0

如果您选择超出完整的Rails范围,但愿意使用active_support(gem install actionview),这里有一个完整的示例:

#!/usr/bin/env ruby

require 'active_support'
require 'active_support/core_ext/object/acts_like'
require 'active_support/core_ext/time/acts_like'
require 'action_view'

require 'date'

# Avoid a deprecation warning
I18n.enforce_available_locales = false

# Add time_ago_in_words
extend ActionView::Helpers::DateHelper

[
  '2014-04-24 16:20:00',
  '2014-04-21 16:20:00',
  '2014-03-24 16:20:00',
  '2013-04-20 16:20:00',
].map {|t| DateTime.parse t}.each do |time|
  puts time_ago_in_words time
end

在撰写本文时,这将输出:

about 6 hours
3 days
about 1 month
about 1 year

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接