80

有没有人有一个很好的正则表达式模式来匹配iso日期时间?

即:2010-06-15T00:00:00

4

10 回答 10

130

对于严格的完整日期时间,包括毫秒,根据W3C 对规范的要求

//-- Complete precision:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/

//-- No milliseconds:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)/

//-- No Seconds:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)/

//-- Putting it all together:
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/

.
实际ISO 8601:2004(E) 文档允许的其他变化:

/********************************************
**    No time-zone varients:
*/
//-- Complete precision:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+/

//-- No milliseconds:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d/

//-- No Seconds:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d/

//-- Putting it all together:
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d)/

警告:这一切都会很快变得一团糟,它仍然允许某些废话,例如第 14 个月。此外,ISO 8601:2004(E) 允许其他几种变体。

.
“2010-06-15T00:00:00”是不合法的,因为它没有指定时区。

于 2010-06-29T17:34:13.713 回答
15

要仅匹配 ISO 日期,例如 2017-09-22,您可以使用此正则表达式:

^\d{4}-([0]\d|1[0-2])-([0-2]\d|3[01])$

它将匹配任何数字年份、由 00-12 范围内的两位数指定的任何月份以及由 00-31 范围内的两位数指定的任何日期

于 2017-09-22T10:10:43.403 回答
9

我将最佳答案改写为更简洁的内容。不是写出三个可选模式中的每一个,而是将元素嵌套为可选语句。

/[+-]?\d{4}(-[01]\d(-[0-3]\d(T[0-2]\d:[0-5]\d:?([0-5]\d(\.\d+)?)?[+-][0-2]\d:[0-5]\dZ?)?)?)?/

我很好奇这种方法是否有缺点?

您可以在这里找到我建议的答案的测试:http ://regexr.com/3e0lh

于 2016-08-12T17:30:28.903 回答
6

这是检查 ISO 8601日期格式的正则表达式,包括闰年和短长月。要运行它,您需要“忽略空白”。regexlib 上有一个没有空格的压缩版本:http: //regexlib.com/REDetails.aspx?regexp_id=3344

ISO 8601 还有更多内容——这个正则表达式只关心日期,但您可以轻松扩展它以支持时间验证,这并不那么棘手。

更新:这现在适用于 javascript(没有后视)

  ^(?:
      (?=
            [02468][048]00
            |[13579][26]00
            |[0-9][0-9]0[48]
            |[0-9][0-9][2468][048]
            |[0-9][0-9][13579][26]              
      )

      \d{4}

      (?:

        (-|)

        (?:

            (?:
                00[1-9]
                |0[1-9][0-9]
                |[1-2][0-9][0-9]
                |3[0-5][0-9]
                |36[0-6]
            )
            |
                (?:01|03|05|07|08|10|12)
                (?:
                  \1
                  (?:0[1-9]|[12][0-9]|3[01])
                )?            
            |
                (?:04|06|09|11)
                (?:
                  \1
                  (?:0[1-9]|[12][0-9]|30)
                )?            
            |
                02
                (?:
                  \1
                  (?:0[1-9]|[12][0-9])
                )?

            |
                W(?:0[1-9]|[1-4][0-9]|5[0-3])
                (?:
                  \1
                  [1-7]
                )?

        )            
      )?
  )$
  |
  ^(?:
      (?!
            [02468][048]00
            |[13579][26]00
            |[0-9][0-9]0[48]
            |[0-9][0-9][2468][048]
            |[0-9][0-9][13579][26]              
      )

      \d{4}

      (?:

        (-|)

        (?:

            (?:
                00[1-9]
                |0[1-9][0-9]
                |[1-2][0-9][0-9]
                |3[0-5][0-9]
                |36[0-5]
            )
            |
                (?:01|03|05|07|08|10|12)
                (?:
                  \2
                  (?:0[1-9]|[12][0-9]|3[01])
                )?

            |
                (?:04|06|09|11)
                (?:
                  \2
                  (?:0[1-9]|[12][0-9]|30)
                )?
            |
                (?:02)
                (?:
                  \2
                  (?:0[1-9]|1[0-9]|2[0-8])
                )?
            |
                W(?:0[1-9]|[1-4][0-9]|5[0-3])
                (?:
                  \2
                  [1-7]
                )?
       ) 
    )?
)$

为了满足时间,在混合物中添加这样的东西(来自: http ://underground.infovark.com/2008/07/22/iso-date-validation-regex/ ):

([T\s](([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)?(\15([0-5]\d))?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?
于 2011-08-28T14:30:08.153 回答
6

我已经制作了这个正则表达式并解决了日期的验证问题,因为它们来自 Javascript 的.toISOString()方法。

^[0-9]{4}-((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01])|(0[469]|11)-(0[1-9]|[12][0-9]|30)|(02)-(0[1-9]|[12][0-9]))T(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9])\.[0-9]{3}Z$

设想:

  • 适当位置的适当符号('-'、'T'、':'、'.'、'Z')。
  • 与 29、30 或 31 天的月份一致。
  • 时间从 00 到 23。
  • 从 00 到 59 的分和秒。
  • 从 000 到 999 的毫秒数。

不考虑:

  • 闰年。

示例日期: 2019-11-15T13:34:22.178Z

直接在 Chrome 控制台中运行的示例: /^[0-9]{4}-((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01])|(0[469]|11)-(0[1-9]|[12][0-9]|30)|(02)-(0[1-9]|[12][0-9]))T(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9])\.[0-9]{3}Z$/.test("2019-11-15T13:34:22.178Z");

正则表达式流程图(Regexper): 正则表达式流程图

于 2019-11-15T13:51:20.890 回答
3

ISO 8601规范允许多种日期格式。这里有一个关于如何做的平庸的解释。Javascript 的日期输入格式与未指定时区的简单日期的 ISO 格式之间存在相当小的差异,并且可以使用字符串替换轻松缓解。完全支持 ISO-8601 规范并非易事。

这是一个参考示例,我不保证它是完整的,尽管它解析了上述 Wikipedia 页面中的非持续时间日期。

下面是一个例子,你也可以在 ideone 上看到它的输出。不幸的是,它不能按规范工作,因为它没有正确实施数周。ISO-8601 中第 01 周的定义很重要,需要浏览日历以确定第一周从哪里开始,以及它在指定年份的天数方面的确切含义。这可能很容易纠正(我只是厌倦了玩它)。

function parseISODate (input) {
    var iso = /^(\d{4})(?:-?W(\d+)(?:-?(\d+)D?)?|(?:-(\d+))?-(\d+))(?:[T ](\d+):(\d+)(?::(\d+)(?:\.(\d+))?)?)?(?:Z(-?\d*))?$/;

    var parts = input.match(iso);

    if (parts == null) {
        throw new Error("Invalid Date");
    }

    var year = Number(parts[1]);

    if (typeof parts[2] != "undefined") {
        /* Convert weeks to days, months 0 */
        var weeks = Number(parts[2]) - 1;
        var days  = Number(parts[3]);

        if (typeof days == "undefined") {
            days = 0;
        }

        days += weeks * 7;

        var months = 0;
    }
    else {
        if (typeof parts[4] != "undefined") {
            var months = Number(parts[4]) - 1;
        }
        else {
            /* it's an ordinal date... */
            var months = 0;
        }

        var days   = Number(parts[5]);
    }

    if (typeof parts[6] != "undefined" &&
        typeof parts[7] != "undefined")
    {
        var hours        = Number(parts[6]);
        var minutes      = Number(parts[7]);

        if (typeof parts[8] != "undefined") {
            var seconds      = Number(parts[8]);

            if (typeof parts[9] != "undefined") {
                var fractional   = Number(parts[9]);
                var milliseconds = fractional / 100;
            }
            else {
                var milliseconds = 0
            }
        }
        else {
            var seconds      = 0;
            var milliseconds = 0;
        }
    }
    else {
        var hours        = 0;
        var minutes      = 0;
        var seconds      = 0;
        var fractional   = 0;
        var milliseconds = 0;
    }

    if (typeof parts[10] != "undefined") {
        /* Timezone adjustment, offset the minutes appropriately */
        var localzone = -(new Date().getTimezoneOffset());
        var timezone  = parts[10] * 60;

        minutes = Number(minutes) + (timezone - localzone);
    }

    return new Date(year, months, days, hours, minutes, seconds, milliseconds);
}

print(parseISODate("2010-06-29T15:33:00Z-7"))
print(parseISODate("2010-06-29 06:14Z"))
print(parseISODate("2010-06-29T06:14Z"))
print(parseISODate("2010-06-29T06:14:30.2034Z"))
print(parseISODate("2010-W26-2"))
print(parseISODate("2010-180"))
于 2010-06-29T23:05:09.453 回答
3

yyyy-MM-dd

对这里的大多数答案的解释太多了,这是@Sergey答案的简短变体,解决了一些奇怪的场景(比如2020-00-00),RegExp这只关心yyyy-MM-dd日期:

// yyyy-MM-dd
^\d{4}-([0][1-9]|1[0-2])-([0-2][1-9]|[1-3]0|3[01])$

这个也不关心每个月的天数,比如2020-11-31(因为 11 月只有 30 天)。

我的用例是将 a 转换String为 a Date(从API参数),我只需要知道输入字符串不包含奇怪的东西,我对实际Date对象进行下一次验证。

于 2020-11-20T19:59:53.850 回答
1

从 1900 年到 2999 年的 02/29 验证

 (((2000|2400|2800|((19|2[0-9])(0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30)))T([01][0-9]|[2][0-3]):[0-5][0-9]:[0-5][0-9]\.[0-9]{3}Z
于 2019-03-06T14:53:44.723 回答
0

不确定它是否与您要解决的潜在问题相关,但您可以将 ISO 日期字符串作为构造函数 arg 传递给 Date() 并从中获取对象。在将字符串强制转换为日期方面,构造函数实际上非常灵活。

于 2010-06-29T17:42:17.703 回答
0

Brocks answers are good, but should start with ^ and end with $ so as not to allow prefix/suffix characters if all you are trying to match is the date string alone.

于 2021-08-05T00:54:21.983 回答