正则表达式,用于验证正确的ISO8601日期字符串

时间:2019-05-10 14:44:15

标签: java regex regex-group regex-greedy isodate

例如:2013-08-11T17:22:04.51+01:00

在此stackoverflow answer中,不包含 .51 部分的ISODateTime。

请帮助更正此正则表达式

^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:Z|[+-][01]\d:[0-5]\d)$

处理我的格式。

3 个答案:

答案 0 :(得分:1)

此正则表达式应完成以下工作:

    $reader = new \XMLReader(); 
    //https://www.php.net/manual/en/book.xmlreader.php

    // path to the file, the LIBXML_NOCDATA will help if you have CDATA in your 
    // content
    $reader->open($xmlPath, 'ISO-8859-1', LIBXML_NOCDATA); 

    while ($reader->read()) {
        if ($reader->nodeType == XMLReader::ELEMENT) {

                try {

                    $xmlNode = new \SimpleXMLElement($reader->readOuterXml());
                    // do what ever you want

                } catch (\Throwable $th) {
                  // hanlde error
               }
        }
    }

参考https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/

答案 1 :(得分:1)

有时候,正则表达式很方便,但是通常很难阅读,并且(如您所经历的)很难调试。 Java具有内置的ISO 8601格式的解析和验证功能,它接受带和不带小数的字符串,例如.51。我知道您在问,因为您需要通过javax.validation进行验证,而这需要一个正则表达式。因此,仅对于其他读者:选择是显而易见的:不要在这里使用正则表达式。

    try {
        OffsetDateTime.parse("2013-08-11T17:22:04.51+01:00");
        System.out.println("Valid ISO 8601");
    } catch (DateTimeParseException e) {
        System.out.println("Not valid ISO 8601");
    }
  

有效的ISO 8601

注意事项:OffsetDateTime.parse仍不接受ISO 8601的所有变体,但比正则表达式要多得多。

答案 2 :(得分:0)

使用捕获组,您可以简单地设计一个表达式以捕获您希望从输入中获取的任何内容。例如this expression

(\d{4}-\d{2}-\d{2})[A-Z]+(\d{2}:\d{2}:\d{2}).([0-9+-:]+)

将输入分为三个捕获组,您可以简单地使用$ 1- $ 3进行调用。

您还可以在[]中添加任何想要的字符。

enter image description here

RegEx描述图

此图显示了表达式的工作方式,您可以在此link中可视化其他表达式:

enter image description here

Java测试

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "(\\d{4}-\\d{2}-\\d{2})[A-Z]+(\\d{2}:\\d{2}:\\d{2}).([0-9+-:]+)";
final String string = "2013-08-11T17:22:04.51+01:00";
final String subst = "\\1 \\2 \\3";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);

// The substituted value will be contained in the result variable
final String result = matcher.replaceAll(subst);

System.out.println("Substitution result: " + result);

JavaScript演示

const regex = /(\d{4}-\d{2}-\d{2})[A-Z]+(\d{2}:\d{2}:\d{2}).([0-9+-:]+)/gm;
const str = `2013-08-11T17:22:04.51+01:00`;
const subst = `\nGroup 1: $1\nGroup 2: $2\nGroup 3: $3\n`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);

基本性能测试

此JavaScript代码段使用简单的100万次for循环来显示表达式的性能。

const repeat = 1000000;
const start = Date.now();

for (var i = repeat; i >= 0; i--) {
	const string = '2013-08-11T17:22:04.51+01:00';
	const regex = /(\d{4}-\d{2}-\d{2})[A-Z]+(\d{2}:\d{2}:\d{2}).([0-9+-:]+)/gm;
	var match = string.replace(regex, "\nGroup #1: $1 \n Group #2: $2 \n Group #3: $3 \n");
}

const end = Date.now() - start;
console.log("YAAAY! \"" + match + "\" is a match  ");
console.log(end / 1000 + " is the runtime of " + repeat + " times benchmark test.  ");