确保字符串是时间或日期格式?

时间:2010-08-05 10:34:49

标签: ruby regex

我有一个将字符串解析为日期的方法,但我想验证我不会尝试解析非数字字符串或代表日期或时间格式的字符串?

怎么能这个?

目前我有:

if(string=~ /^\D*$/ )
{
return false
else 
do something_else
}

对于像"UNKNOWN"这样的非数字字符串,这很好,但不适用于"UNKNOWN1"

知道我可以用什么来确保只解析日期或时间格式?

5 个答案:

答案 0 :(得分:13)

DateTime.strptime v ParseDate.parsedate

没有任何双关语,但此处的信息现已过时(2015年),并且已从Ruby 2.x中删除了一些方法和模块,我将其留在此处以防万一有人,某处仍在使用1.8 .7

好吧,也许那里有一个小双关语;-)


你会认为你可以使用 Date.parse DateTime.parse 来检查错误的日期(详见Date.parse here

d = Date.parse(string) rescue nil

if d 
   do_something
else
   return false
end

因为错误的值会抛出一个你可以捕获的异常。但是,建议的测试字符串实际上返回Date with Date.parse

例如......

~\> irb
>> Date.parse '12-UNKN/34/OWN1'
=> #<Date: 4910841/2,0,2299161>
>> 

Date.parse只是不够聪明地完成这项工作: - (

ParseDate.parsedate做得更好。您可以看到它尝试解析日期,但在测试示例中,找不到有效的年份或月份。更多信息here

>> require 'parsedate'
=> true
>> ParseDate.parsedate '2010-09-09'
=> [2010, 9, 9, nil, nil, nil, nil, nil]
>> ParseDate.parsedate 'dsadasd'
=> [nil, nil, nil, nil, nil, nil, nil, nil]
>> ParseDate.parsedate '12-UNKN/34/OWN1'
=> [nil, nil, 12, nil, nil, nil, nil, nil]
>> ParseDate.parsedate '12-UNKN/34/OWN1'
=> [nil, nil, 12, nil, nil, nil, nil, nil]

答案 1 :(得分:1)

无论您使用哪种方法来解析日期,都可以通过重新格式化生成的日期并将其与原始输入进行比较来验证严格一致性。例如:

def strict_parse(input, format)
  Time.strptime(input, format).tap { |output| expect(output.strftime(format)).to eq input }
end

这是严格但是,例如"1/9/2014"不会使用格式"%d/%m/%Y"进行解析。它必须是"01/09/2014"才能被接受。

答案 2 :(得分:0)

Ruby的解析器是乐观的,如果你可以抛出一堆垃圾并从输入字符串中获得结果, Date.parse DateTime.strptime 会尝试做到这一点。

你想要一个悲观和严格的检查,这意味着在尝试用正则表达式寻找垃圾之后不要假设接受,你应该假设拒绝并用你的正则表达式寻找宝藏。

你的第一个检查:“是字符串数字”是使用正则表达式来尝试找到一个完全由非数字字符组成的字符串,如果找到它则拒绝。 \ D(使用大写字母D)正在查找非数字字符,如果输入字符串完全由0个或更多非数字字符组成,则输入字符串将仅匹配正则表达式。

你可能会对数字的以下逻辑有更好的运气:

if(string=~ /^\d*$/ )
 something_else
else 
 return false
end

匹配一个完全由0个或更多数字字符组成的字符串,如果找到则 something_else ,否则返回false。

您希望明确搜索时间并拒绝所有其他值。对于HH:MM:SSAM格式,它允许省略每个字段的前导0,12小时可以使用以下内容:

if (string =~ /^[01]?\d:[0-5]?\d:[0-5]?\d[AP]M$/)
  something_else
else
  return false
end

同样,对于您希望显式搜索有效日期的日期,并拒绝所有其他值。对于MM / DD / YYYY,它可以容忍在除了年份之外的所有内容中省略前导0,你可以选择:

if (string =~ /^[0-1]\d\/[0-3]?\d\/\d{4}/)
  something_else
else
  return false
end

Ruby的实用函数试图在它们接受的内容中详细说明,但对于不是有用特性的验证。要严格,假设一切都无效,直到证明不然,然后接受它。

答案 3 :(得分:0)

我建议您建立一个您期望并打算支持的日期和日期时间格式列表。您可以使用strftime兼容字符串定义它们,然后在使用DateTime#strptime解析日期时使用相同的字符串。尝试使用每个支持的模式解析输入字符串,第一个不抛出异常的模式将返回解析日期。如果每个都抛出异常,则该字符串不是有效日期。

答案 4 :(得分:0)

检查一下:

如果字符串是有效时间,则返回true,否则返回false:

let counter = 0;

function doSomething() {
    c.log(counter);
    ++counter;
    test();
}

function test() {
    counter <= 50 ? doSomething() : null;
}

test(80);

如果字符串是有效日期,则返回true,否则返回false:

require 'time'

def is_a_time?(string)
  !!(Time.parse(string) rescue false)
end