Regex en ISO8601 geformatteerde DateTime

Ik heb een DateTime-string ISO8601 geformatteerd

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

en de volgende Regex die niet overeenkomt met deze tekenreeks

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

Ik begrijp niet waarom het niet overeenkomt.

Ik ben ontsnapt aan metakarakters, voor mij lijkt het OK.

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

BEWERKEN:

Op de juiste manier: http://jsfiddle.net/5n5vk/3/


Antwoord 1, autoriteit 100%

Onvolledige Regex

Het is onvolledig omdat het komt overeen met een ongeldige datumzoals 2013-99-99T04:13:00+00:00.

Betere oplossing

De onderstaande regex komt niet overeen met dit soort ongeldige datum (zie ISO 8601-datumvalidatie die niet slecht is). U kunt testen met de volgende 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]); }
}

Antwoord 2, autoriteit 72%

Ik vond de RegExp die ook de datum probeert te valideren een beetje overdreven voor mij. Ik wilde alleen weten of een string een ISO 8601-datumstring bevat. Ik controleer of de datum echt geldig is nadat ik deze heb omgezet in een Datum object.

Hier zijn 2 versies van de RegExp. Hiermee wordt eerst gecontroleerd of de string een geldige ISO 8601-datumstring is. De andere tests voor een volledige datumreeks inclusief de uren/minuten/seconden (vaak gebruikt 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

Antwoord 3, autoriteit 42%

Citeer de regex niet bij het specificeren van een regex in js. Een schuine streep naar voren is voldoende.

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

Antwoord 4, autoriteit 15%

JavaScript date.toISOString() regex

Dit probeert alleen het basispatroon van 2017-06-17T00:00:00.000Zop te lossen dat u van Javascript verwacht.

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

Een van de meest irritante dingen van JSON is dat je niet zomaar een datum kunt doorgeven en verwachten dat deze correct wordt geconverteerd. Aangezien de meeste mensen JavaScript gebruiken, is dit waarschijnlijk praktisch.

Hier is een demofragment als je moet doorgeven aan Mongo en moet converteren.

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

Ik beweer dat dit een betere benadering is, omdat je er zeker van kunt zijn dat de datum wordt geparseerd, waarna je het gewenste bereik kunt controleren, allemaal vrij eenvoudig en gemakkelijk te onderhouden, omdat regex geweldig is, maar tot op zekere hoogte.


Antwoord 5

Wat dacht je van alleen testen als je een Date-object van de string kunt maken, als dat het doel van de test is?

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

Antwoord 6

Om aan al deze goede antwoorden toe te voegen, vond ik dat deze best goed werkte voor alleen ISO-datums (geen tijd)

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

Other episodes