Ruby/Rails:将日期时间转换为自然语言(例如 2012 年 3 月 23 日到“本周五”)

Posted

技术标签:

【中文标题】Ruby/Rails:将日期时间转换为自然语言(例如 2012 年 3 月 23 日到“本周五”)【英文标题】:Ruby/Rails: Converting datetime to natural language (e.g. 3/23/2012 to "this Friday") 【发布时间】:2012-04-04 11:22:32 【问题描述】:

是否有人知道 gem、方法或代码 sn-p 可以将日期时间值转换为更人性化的时间,而无需创建一系列规则或在视图中放置一堆逻辑?例如:如果今天是 3/19/2012,则转换:

2012 年 3 月 23 日至“本周五” 2012 年 3 月 26 日至“下周一” 2012 年 3 月 31 日至“下周末” 2012 年 4 月 15 日至“下个月” 2012 年 3 月 15 日至“上周四” 2011 年 3 月 1 日至“去年”

基本上,我正在寻找 Chronic gem 的反面。与distance_of_time_in_words 更相似的东西,但有所不同。我不想从数据库中获取日期并按原样显示它们,而是想让它们在显示给最终用户时更加人性化和相关。

【问题讨论】:

您希望 3/9/2012 和 4/6/2012 说什么? 这应该是一个非常容易编写的助手,假设你的规则基本上和你提出的一样简单,那么只需将它粘贴到 application_helper.rb 或创建一个库和 bada-bing。看起来很有趣——如果有时间,我会写一些入门代码并发布答案。 @James- 我猜分别是“上周”和“下个月”。如果您正在与某人交谈,您认为最合适的方式是什么?这些响应是否会使干净地创建可重复的算法变得更加困难? 【参考方案1】:

我修改了Tom’s answer 以满足我的需要,并且可以作为独立模块使用,而无需将其包含在任何地方。我将文件human_date.rb 放在我的lib 目录中。我还修复了 days_difference 计算的一个棘手问题。

module HumanDate
  include ActionView::Helpers::DateHelper
  extend self

  def date_distance(from, to, long_form = true)
    seconds_in_day = 60 * 60 * 24
    days_difference = ((to.beginning_of_day.to_datetime - from.beginning_of_day.to_datetime)).floor
    case days_difference
      when -2
        "day before yesterday"
      when -1
        "yesterday"
      when 0
        "today"
      when 1
        "tomorrow"
      when 2..6
        "this #day_name(days_difference)"
      when 7..13
        "next #to.strftime("%a") (#short_date(days_difference))"
      else
        if days_difference > 0
          "in #distance_of_time_in_words(from, to) (#short_date(days_difference, long_form))"
        else
          "#distance_of_time_in_words(from, to) ago (#short_date(days_difference, long_form))"
        end
    end
  end

  def short_date(this_many, include_day=false)
    format_string = "%-b %-d"
    format_string = "%a, #format_string" if include_day
    this_many.days.from_now.strftime(format_string)
  end

  def day_name(this_many)
    this_many.days.from_now.strftime("%A")
  end

  def days_left_in_month
    Time.now.end_of_month.day - Time.now.day
  end

  def days_left_in_week
    Time.now.end_of_week.day - Time.now.day
  end
end

用法:

1.9.3-p392 :001 > HumanDate. date_distance(Time.now, 2.day.ago)
 => "day before yesterday" 
1.9.3-p392 :002 > HumanDate. date_distance(Time.now, 3.days.from_now)
 => "this Tuesday" 
1.9.3-p392 :003 > HumanDate. date_distance(Time.now, 12.days.from_now)
 => "next Thursday (Aug 1)" 
1.9.3-p392 :004 > HumanDate. date_distance(Time.now, 122.days.from_now)
 => "in 4 months (Tue, Nov 19)" 
1.9.3-p392 :005 > HumanDate. date_distance(Time.now, 122.days.ago)
 => "4 months ago (Wed, Mar 20)" 

【讨论】:

特别针对 Rails 新手:将文件放在 config/initializers。在您的模板上HumanDate.date_distance(Date.today, @post.my_date)【参考方案2】:

Hublot gem 的目标是解决这个问题——成为一个“逆向慢性”。

https://github.com/brettshollenberger/hublot

相关问题:Ruby/Rails - Convert Date/Time back into Natural Language (2011-02-17 => February 17th, 2011)

【讨论】:

Hublot gem(在这种情况下)的问题在于它在日期时间而不是天数上运行。所以你会在“明天”得到“明天中午 12 点”。【参考方案3】:

这是一个小技巧,完全未完成且不雅。但是 Ruby/Rails 的日期非常棒,范围也非常完美,也许如果你没有找到 gem,这样的东西会让你开始:

module HumanDate
  def date_difference_for_people (from, to)
    seconds_in_day = 24 * 60 * 60
    days_difference = ((to - from)/seconds_in_day).round
    case days_difference
      when -1
        "yesterday"
      when 0
        "today"
      when 1
        "tomorrow"
      when 2..days_left_in_week
        "this #day_name(difference)"
      when (days_left_in_week + 1)..(days_left_in_week + 7)
        "next week"
      when (days_left_in_week + 8)..days_left_in_month
        "later this month"
      else
        "later -- how much left to you :-)"
    end
  end

  def day_name(days_from_now)
    days_from_now.days_from_now.strftime("%A")
  end

  def days_left_in_month
    Time.now.end_of_month.day - Time.now.day
  end

  def days_left_in_week
    Time.now.end_of_week.day - Time.now.day
  end
end

【讨论】:

以上是关于Ruby/Rails:将日期时间转换为自然语言(例如 2012 年 3 月 23 日到“本周五”)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用ruby / rails将所有大写字母转换为适当的首字母大写字母,其余为小写?

Ruby/Rails 中的夏令时开始和结束日期

Ruby on Rails 取消首字母大写

清理 URL slug 的 Unicode 字符串(Ruby/Rails)

将 NTP 字符串转换为日期时间

Ruby on Rails 学习五Ruby语言的方法