Javascript 正则表达式和 ISO8601 格式的日期时间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12756159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 11:11:36  来源:igfitidea点击:

Regex and ISO8601 formatted DateTime

javascriptregexdatetimeiso8601

提问by TwystO

I have a DateTime string ISO8601 formated

我有一个格式化的日期时间字符串 ISO8601

2012-10-06T04:13:00+00:00

and the following Regex which does not match this string

以及以下与此字符串不匹配的正则表达式

#(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})\+(\d{2})\:(\d{2})#

I can't figure out why it does not match.

我不明白为什么它不匹配。

I escaped metacharacters, for me it seems to be OK.

我转义了元字符,对我来说似乎没问题。

http://jsfiddle.net/5n5vk/2/

http://jsfiddle.net/5n5vk/2/

EDIT :

编辑 :

The right way: http://jsfiddle.net/5n5vk/3/

正确的方法:http: //jsfiddle.net/5n5vk/3/

采纳答案by Peter Kuhar

Don't quote the regex when specifying a regex in js. Forward slash is enough.

在 js 中指定正则表达式时不要引用正则表达式。正斜杠就够了。

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');
}?

回答by édouard Lopez

Incomplete Regex

不完整的正则表达式

It's incomplete as it matches invalid datesuch as 2013-99-99T04:13:00+00:00.

它不完整,因为它匹配无效日期,例如2013-99-99T04:13:00+00:00.

Better solution

更好的解决方案

The regex below won't match this kind of invalid date (cf. ISO 8601 Date Validation That Doesn't Suck). You can test with the following code :

下面的正则表达式与这种无效日期不匹配(参见ISO 8601 Date Validation That Not Suck)。您可以使用以下代码进行测试:

re = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(([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+(?!:))?)?([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]); }
}

回答by SnailCrusher

I found the RegExp that also tries to validate the date a bit overkill for me. I Just wanted to know if a string contains an ISO 8601 date string. I'll check if the date is actually valid after I have converted it to a Dateobject.

我发现 RegExp 也试图验证日期对我来说有点矫枉过正。我只是想知道一个字符串是否包含 ISO 8601 日期字符串。在将日期转换为Date对象后,我将检查该日期是否实际有效。

Here are 2 versions of the RegExp. This first checks if the string is a valid ISO 8601 date string. The other tests for a full date string including the hours/minutes/seconds (Commonly used in API's)

这里有 2 个版本的 RegExp。这首先检查字符串是否是有效的 ISO 8601 日期字符串。完整日期字符串的其他测试,包括小时/分钟/秒(常用于 API)

/**
 * 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

回答by Jason Sebring

JavaScript date.toISOString() regex

JavaScript date.toISOString() 正则表达式

This only attempts to solve the basic pattern of 2017-06-17T00:00:00.000Zthat you expect from Javascript doing it.

这只是试图解决2017-06-17T00:00:00.000Z您期望从 Javascript 执行它的基本模式。

const isoPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;

One of the most annoying things about JSON is one cannot simply pass a date through and expect it to convert properly. Since most people use JavaScript, this is probably practical.

JSON 最烦人的事情之一是不能简单地传递日期并期望它正确转换。由于大多数人使用 JavaScript,这可能是实用的。

Here's a demo snippet if you have to pass to mongo and need to convert.

如果您必须传递给 mongo 并需要转换,这里有一个演示片段。

if (isoPattern.test(json.startDate))
  json.startDate = new Date(json.startDate);

I argue this is a better approach as you can be assured the date will parse, then you can check desired range, all being pretty straight forward and easy to maintain as regex is great but to a point.

我认为这是一种更好的方法,因为您可以确定日期会被解析,然后您可以检查所需的范围,所有这些都非常直接且易于维护,因为正则表达式很棒但在一定程度上。

回答by patriques

How about only testing if you can create a Date object of the string, if that is the purpose of the test?

如果您可以创建字符串的 Date 对象,那么仅测试如何,如果这是测试的目的?

new Date("2016-05-24T15:54:14.876Z").toString() === 'Invalid Date' // false
new Date("Invalid date").toString() === 'Invalid Date' // true

回答by stallingOne

To add to all these good answers, I found this one to be working quite good for just ISO dates (no time)

为了添加所有这些好的答案,我发现这个只适用于 ISO 日期(没有时间)

(?: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=pass x=does-not-pass)

(v=pass x=does-not-pass)

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