日期时间格式的正则表达式:“2012年8月8日星期三9:38:31.113 AM”

时间:2012-08-09 16:51:08

标签: java regex

我目前有:

(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday),?\s+(January|February|March|April|May|June|July|August|September|October|November|December)\s+[0-3]?[0-9],?\s+[0-2][0-9][0-9][0-9],?\s+([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-9][0-9][0-9],?\s+(AM|PM)

...作为我的正则表达式,但在使用一点测试工具断言时,我发现它失败了。搞砸了哪里?我从Web应用程序获取日期时间文本并断言它与上面的正则表达式匹配。

4 个答案:

答案 0 :(得分:6)

作业的错误工具

正在尝试修复你的正则表达式的所有其他答案的事实是你的正则表达式的另一部分,你错了;这应该告诉你它不适合这项工作。

当它们短而紧凑时,正常的表达很难做到,这个长度中的一个将是一个噩梦,以便正确,然后没有人能够在将来触摸它,因为害怕以某种神秘的方式打破它

Idiomatic Java

SimpleDateFormat.parse()是用Java处理String格式的日期信息的惯用方法。

正则表达式用于匹配

  

有些人在遇到问题时会想“我知道,我会用   正则表达式。“现在他们有两个问题 - Jamie Zawinski

that quote来自alt.religion.emacs邮件列表!

糟糕的解决方案,以说明为什么SimpleDateFormat.parse()是正确的做法。

无论如何,你可以将你想要的东西与正则表达式匹配,但你应该做你想要做的所有验证。您正在将验证逻辑与匹配逻辑混淆,两者似乎在某些方面重叠,但在这种情况下,验证应该是代码,而不是正则表达式测试。

(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday), (January|February|March|April|May|June|July|August|September|October|November|December) (\d{2}), (\d{4}) (\d{1,2}):(\d{2}):(\d{2})\.(\d{3}) (AM|PM)

上述表达式将匹配您在标题中请求的字符串。但它没有尝试验证数字的范围,如果你这样做了,你打算做什么关于闰年和二月?,一个正则表达式会更难以维持。

在这种情况下,您应该使用正则表达式对数据进行分类,以确保匹配模式或格式,然后将其传递给真正的解析器或传递组一个实际进行范围验证和其他事情的方法。

答案 1 :(得分:0)

正则表达式可能不是解析日期的最佳工具,但是这是你的正则表达式中唯一突出的东西。

您的时间似乎需要三位数秒,而且不包括毫秒:

([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-9][0-9][0-9]

尝试将其更改为以下内容:

([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-9]{2}\.[0-9]{3}

请注意,如果您想保存一些字符,也可以将所有[0-9]更改为\d

答案 2 :(得分:0)

你遗漏了Seconds,你在正则表达式中使用:表示毫秒,但在问题标题示例中使用.。所以试试:

(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday),?\s+(January|February|March|April|May|June|July|August|September|October|November|December)\s+[0-3]?[0-9],?\s+[0-2][0-9][0-9][0-9],?\s+([01]??[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9].[0-9][0-9][0-9],?\s+(AM|PM)

答案 3 :(得分:0)

虽然我同意前面的发言者认为regexp不适合这项工作,但这里是一个自动生成的代码段,与您的确切日期相符:

import java.util.regex.*;

class Main
{
  public static void main(String[] args)
  {
    String txt="Wednesday, August 08, 2012 9:38:31.113 AM";

    String re1="((?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday|Tues|Thur|Thurs|Sun|Mon|Tue|Wed|Thu|Fri|Sat))";    // Day Of Week 1
    String re2=".*?";   // Non-greedy match on filler
    String re3="((?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Sept|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?))";   // Month 1
    String re4=".*?";   // Non-greedy match on filler
    String re5="((?:(?:[0-2]?\\d{1})|(?:[3][01]{1})))(?![\\d])";    // Day 1
    String re6=".*?";   // Non-greedy match on filler
    String re7="((?:(?:[1]{1}\\d{1}\\d{1}\\d{1})|(?:[2]{1}\\d{3})))(?![\\d])";  // Year 1
    String re8=".*?";   // Non-greedy match on filler
    String re9="(\\d+)";    // Integer Number 1
    String re10=".*?";  // Non-greedy match on filler
    String re11="(\\d+)";   // Integer Number 2
    String re12=".*?";  // Non-greedy match on filler
    String re13="(\\d+)";   // Integer Number 3
    String re14=".*?";  // Non-greedy match on filler
    String re15="(\\d+)";   // Integer Number 4
    String re16=".*?";  // Non-greedy match on filler
    String re17="((?:[a-z][a-z]+))";    // Word 1

    Pattern p = Pattern.compile(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12+re13+re14+re15+re16+re17,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    Matcher m = p.matcher(txt);
    if (m.find())
    {
        String dayofweek1=m.group(1);
        String month1=m.group(2);
        String day1=m.group(3);
        String year1=m.group(4);
        String int1=m.group(5);
        String int2=m.group(6);
        String int3=m.group(7);
        String int4=m.group(8);
        String word1=m.group(9);
        System.out.print("("+dayofweek1.toString()+")"+"("+month1.toString()+")"+"("+day1.toString()+")"+"("+year1.toString()+")"+"("+int1.toString()+")"+"("+int2.toString()+")"+"("+int3.toString()+")"+"("+int4.toString()+")"+"("+word1.toString()+")"+"\n");
    }
  }
}

如果有人故意想要可怕的正则表达式,那么网上有一个很棒的工具:http://txt2re.com/