Ruby 如何将简单的时间字符串解析为时间段?
在我的Ruby应用程序中,我有一个Ruby 如何将简单的时间字符串解析为时间段?,ruby,datetime,Ruby,Datetime,在我的Ruby应用程序中,我有一个投资实体,它有一个术语属性 我需要这个类接受用户输入的字符串,格式为3年或36个月。然后,我想将输入转换为月数,将term属性设置为this period并计算到期日 到目前为止,我已经尝试使用主动支持和慢性支持,但API不支持这一点 此getter的工作原理是: def term if term =~ /year[s]?/i term = term.to_i * 12 else term =~ /month[s]?/i
投资
实体,它有一个术语
属性
我需要这个类接受用户输入的字符串,格式为3年
或36个月
。然后,我想将输入转换为月数,将term
属性设置为this period并计算到期日
到目前为止,我已经尝试使用主动支持和慢性支持,但API不支持这一点
此getter的工作原理是:
def term
if term =~ /year[s]?/i
term = term.to_i * 12
else term =~ /month[s]?/i
term = term.to_i
end
end
但是在Ruby中有没有更优雅的方法来实现这一点呢?如果我们可以假设输入字符串总是包含一个或多个数字,后跟一个单位(“年”、“年”、“月”等等),那么这是非常简单的。只需编写一个正则表达式,捕获数字和单位,将数字转换为数字并规范化单位,然后进行数学运算
def to_months(str)
if str =~ /(\d+)\s*(month|year)s?/i
num = $1.to_i # => 3
unit = $2.downcase # => year
num *= 12 if unit == "year"
return num
end
raise ArgumentError, "Invalid input"
end
puts to_months("3 Years") # => 36
puts to_months("1 month") # => 1
puts to_months("6months") # => 6
它并不比你的方法优雅多少,但也许它会给你一个或两个想法。Ruby没有任何内置的表示“时间跨度”的东西(其他一些语言有)。然而,有一个问题,尽管这可能有点过分了你的情况 您提到,
chronic
不支持这一点。但是为什么不自己计算时差呢
require 'chronic'
input = '2 years'
then = Chronic.parse(input + ' ago')
now = Time.now
# Now we just calculate the number of months
term = (now.year * 12 + now.month) - (then.year * 12 + then.month)
这样,您就可以灵活地进行慢性的解析,并且仍然不需要太多的代码
或者直接使用timespan
库
require 'timespan'
term = Timespan.new('2 years').to_months
# Boom.
听起来像是在试图解析向用户显示的标签,而不是向方法传递一个更容易计算的值。e、 g.在选择框中,选项标签可显示标签“3年”,但选项值应为整数36。因此,用户选择一个易于阅读的文本标签,但您将一个表示月数的整数传递给您的方法,这样就不需要解析字符串了。问得好!但如果这是唯一的需要,我对你的方法很在行。那么秒可能是你最好的选择。ChronicDuration可以将3年
和36个月
解析为秒。你会遇到这样一个问题,3年36个月是不一样的,这取决于你如何计算它@theTinMan:这就是为什么你不让他们破坏你的应用程序。您可以添加错误处理。不管您是否允许自由文本,您都需要它。@theTinMan:是的,显然您不想为应用程序中的每个输入表单定义DSL。在这种情况下,自由文本通常不适合使用。但在某些情况下,很难有一个好的UI,它的限制性足以避免歧义,但允许性足以不打扰用户(例如,向配方应用程序添加配料)。在这种情况下,一种选择是允许自由文本,以及一些(希望)健壮的解析,从而为用户提供所需的灵活性。不过,OP的情况可能并非如此。