以前的时间转换为系统日期时间

Time ago in words convert into system date-time

正在尝试将 9 weeks ago1 year, 6 months ago20 hours ago 等字符串转换为 ruby 时间对象,如 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,所以没有花哨的 rails 助手。

不言而喻,这很容易出错。使用风险自负:

def parse(date:)
  eval(date.gsub(/ ?(,|and) ?/, '+').tr(' ', '.').gsub(/^(.*)(\.ago)$/, '()'))
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'

请不要在生产代码中使用 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)>