尝试将9 weeks ago
,1 year, 6 months ago
,20 hours ago
等字符串转换为像Tue, 10 Mar 2015 12:06:15 PDT -07:00
这样的红宝石时间对象。
我一直这样做:
eval("10 days ago".gsub(' ', '.'))
这样可以正常工作,但是像1 year, 6 months ago
这样的字符串会爆炸。
我只需要进行比较,如:
eval("10 days ago".gsub(' ', '.')) < (Time.now - 7.days)
我使用 sinatra 所以没有花哨的铁路助手。
答案 0 :(得分:1)
不言而喻,这很容易出错。使用风险由您自行承担:
def parse(date:)
eval(date.gsub(/ ?(,|and) ?/, '+').tr(' ', '.').gsub(/^(.*)(\.ago)$/, '(\1)\2'))
end
parse(date: '1 year, 6 months ago') # => Wed, 10 Sep 2014 21:29:11 BST +01:00
parse(date: '1 year, 6 months, 3 weeks, 6 days, 9 hours and 12 seconds ago')
# => Thu, 14 Aug 2014 12:33:07 BST +01:00
我们的想法是将原始字符串转换为:
'(1.year+6.months).ago'
答案 1 :(得分:1)
请勿在生产代码中使用eval ..
从转换 timeago表示法将非常复杂且资源密集。
但是,这种方式似乎最不容易出错:它会将“5秒前”之类的字符串转换为“5S”并使用mapping
找到它及时的含义,之后它会减去那个时间从目前的时间。
解析字符串是动态构建的,因此它可以容纳大多数每个时间标记。
require('date')
mapping = {"D"=> "%d","W"=>"%U","H"=>"%T","Y"=>"%Y","M"=>"%m","S"=>"%S"}
timerel = "1 year, 6 months ago".split(",").map { |n| n.gsub(/\s+/, "").upcase()[0,2].split('')}
Date.strptime(
timerel.map {|n| n[0]}.join(" "),
timerel.map {|n| mapping[n[1]]}.join(" ")
)
date = Date.new(0) + (Date.today - Date.strptime(timerel.map {|n| n[0]}.join(" "), timerel.map {|n| mapping[n[1]]}.join(" ")))
=> #<Date: 2014-10-10 ((2456941j,0s,0n),+0s,2299161j)>