2016-03-10 1 views
1

Пытается преобразовать строки, такие как 9 weeks ago, 1 year, 6 months ago, 20 hours ago в объект времени с рубином, например Tue, 10 Mar 2015 12:06:15 PDT -07:00.Время от времени в словах convert into system date-time

Я делал это:

eval("10 days ago".gsub(' ', '.')) 

Это прекрасно работает, но для строк, как 1 year, 6 months ago взрывается.

мне просто нужно делать сравнения, как:

eval("10 days ago".gsub(' ', '.')) < (Time.now - 7.days) 

Я использую Синатра так не фантазии не рельсы хелперы.

ответ

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)> 
+1

«Пожалуйста, никогда не используйте eval в производственном коде» -> Неразумное использование 'eval' ... ... неразумно, так же, как неразумное использование любой языковой функции. Пока вы знаете, что делаете, 'eval' в порядке. Это относится ко многим другим языковым функциям (а не только к 'eval'). В этом * конкретном случае, 'eval', вероятно, не очень мудрый, так как« 10 дней назад », вероятно, будет введен пользователем – Carpetsmoker

+1

Хорошая точка. Просто я предпочитаю говорить в абсолютах о чем-то «опасном», таком как «eval» для кого-то (относительно) неопытного. Очень легко начать думать: «О, да, это должен быть один из таких случаев. Позвольте мне просто вывести ol« eval »без правильной перспективы. – octagonal

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' 
Смежные вопросы