Regex and ISO8601 formatted DateTime [duplicate]

只愿长相守 提交于 2019-11-26 10:57:56

问题


I have a DateTime string ISO8601 formated

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/

EDIT :

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


回答1:


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

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



回答2:


Incomplete Regex

It's incomplete as it matches invalid date such as 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 :

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]); }
}



回答3:


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 Date object.

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)

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



回答4:


JavaScript date.toISOString() regex

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

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.

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

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.




回答5:


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

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



回答6:


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

(?: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)

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


来源:https://stackoverflow.com/questions/12756159/regex-and-iso8601-formatted-datetime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!