JavaScript正则expression式isodate时间

有没有人有一个很好的正则expression式模式匹配isodate时间?

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

对于严格的完整date时间(包括毫秒),按照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”是不合法的,因为它没有时区指定。

这里是一个正则expression式来检查ISO 8601的date格式,包括闰年和短的几个月。 要运行这个,你需要“忽略空格”。 没有空格的压缩版本位于regexlib上: http: //regexlib.com/REDetails.aspx?regexp_id=3344

还有更多的ISO 8601 – 这个正则expression式只关心date,但你可以很容易地扩展它来支持时间validation,这不是那么棘手。

更新:这现在与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)?)?)? 

ISO 8601规范允许各种date格式。 关于如何在这里做一个平庸的解释。 JavaScript的dateinput格式和简单date的ISO格式之间有一个相当小的差异,这些date没有指定时区,而且可以使用stringreplace轻松缓解。 完全支持ISO-8601规范是不平凡的。

这是一个参考例子,我不保证是完整的,虽然它从上述维基百科页面parsing非持续时间date。

下面是一个例子,你也可以看到它在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")) 

我把最重要的答案改写成更简洁一些。 而不是写出三个可选模式的每一个,这些元素嵌套为可选语句。

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

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

你可以在这里find我的build议答案的testing: http : //regexr.com/3e0lh

对于只匹配ISOdate,比如2017-09-22,你可以使用这个正则expression式:

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

它将匹配任何数字年份,由范围00-12中的两个数字指定的任何月份和范围00-31中的两个数字指定的任何date

不知道它是否与您正在尝试解决的底层问题有关,但是您可以将ISOdatestring作为构造函数arg传递给Date()并从中获取对象。 构造函数实际上是非常灵活的强制string到date。