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将所有大写字母转换为适当的首字母大写字母,其余为小写?