Regex and ISO8601 formatted DateTime
我有一个日期时间字符串ISO8601格式
1 | 2012-10-06T04:13:00+00:00 |
以及以下与此字符串不匹配的regex
1 | #(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})\+(\d{2})\:(\d{2})# |
我不明白为什么它不匹配。
我逃过了元字符,对我来说似乎没什么问题。
http://jsfiddle.net/5n5vk/2/
编辑:
正确的方法:http://jsfiddle.net/5n5vk/3/
不完整正则表达式
它是不完整的,因为它匹配无效的日期,如
下面的regex与这种无效日期不匹配(参见iso 8601日期验证,这并不糟糕)。可以使用以下代码进行测试:
1 2 3 4 5 6 7 8 9 10 11 | re = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/ var testDates = { 'date' :"2012-10-06T04:13:00+00:00", 'validDate' :"0785-10-10T04:13:00+00:00", 'invalidDate' :"2013-99-99T04:13:00+00:00", '1234Date': '1234' } for (var d in testDates) { if (re.test(testDates[d])) { console.info('[valid]: '+testDates[d]); } else { console.error('[invalid]: '+testDates[d]); } } |
在JS中指定regex时不要引用regex。正斜杠就够了。
1 2 3 4 5 6 7 8 9 | alert($('#datepicker').val()); if($('#datepicker').val().match( /(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})[+-](\d{2})\:(\d{2})/ )) { alert('ok'); } else { alert('not ok'); }? |
我发现regexp也试图验证日期有点过分了。我只是想知道字符串是否包含ISO 8601日期字符串。我将在将日期转换为日期对象后检查该日期是否实际有效。
这里有两个版本的regexp。这首先检查字符串是否是有效的ISO 8601日期字符串。完整日期字符串的其他测试,包括小时/分钟/秒(通常在API中使用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /** * RegExp to test a string for a ISO 8601 Date spec * YYYY * YYYY-MM * YYYY-MM-DD * YYYY-MM-DDThh:mmTZD * YYYY-MM-DDThh:mm:ssTZD * YYYY-MM-DDThh:mm:ss.sTZD * @see: https://www.w3.org/TR/NOTE-datetime * @type {RegExp} */ var ISO_8601 = /^\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\d:\d\d)|Z)?)?)?)?$/i /** * RegExp to test a string for a full ISO 8601 Date * Does not do any sort of date validation, only checks if the string is according to the ISO 8601 spec. * YYYY-MM-DDThh:mm:ss * YYYY-MM-DDThh:mm:ssTZD * YYYY-MM-DDThh:mm:ss.sTZD * @see: https://www.w3.org/TR/NOTE-datetime * @type {RegExp} */ var ISO_8601_FULL = /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(([+-]\d\d:\d\d)|Z)?$/i // Usage: ISO_8601_FULL.test("2016-05-24T15:54:14.876Z" ) // true ISO_8601_FULL.test("2002-12-31T23:00:00+01:00" ) // true ISO_8601_FULL.test("2016-02-01" ) // false ISO_8601_FULL.test("2016" ) // false ISO_8601.test("2016-02-01" ) // true ISO_8601.test("2016" ) // true ISO_8601.test("2002-12-31T23:00:00+01:00" ) // true |
javascript日期.toisString()regex
这只会尝试解决您期望JavaScript执行的
1 | const isoPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/; |
关于JSON,最烦人的事情之一就是不能简单地传递一个日期并期望它正确地转换。因为大多数人使用JavaScript,所以这可能是可行的。
这里有一个演示片段,如果您必须传递给mongo并需要转换。
1 2 | if (isoPattern.test(json.startDate)) json.startDate = new Date(json.startDate); |
我认为这是一个更好的方法,因为您可以确信日期将被解析,然后您可以检查所需的范围,所有这些都是非常直接和易于维护的,因为regex很好,但在一定程度上是。
如果可以创建字符串的日期对象(如果这是测试的目的),那么只进行测试如何?
1 2 | new Date("2016-05-24T15:54:14.876Z").toString() === 'Invalid Date' // false new Date("Invalid date").toString() === 'Invalid Date' // true |
为了补充所有这些好的答案,我发现这一个对于ISO日期(没有时间)非常有效。
1 | (?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31)) |
(V=通过X=未通过)
1 2 3 4 5 6 7 8 | 2016-12-30 v 2016-13-31 x 2016-01-32 x 2016-02-29 v 2016-02-30 x 2017-02-29 v -> that's a false positive 1889-01-01 x -> you can add accepted centuries in the list: (?:18|19|20) 2099-01-01 v |