web-dev-qa-db-fra.com

Regex et DateTime au format ISO8601

J'ai une chaîne DateTime ISO8601 formatée

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

et le Regex suivant qui ne correspond pas à cette chaîne

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

Je ne peux pas comprendre pourquoi cela ne correspond pas.

J'ai échappé aux métacaractères, pour moi ça semble bien.

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

MODIFIER:

La bonne façon: http://jsfiddle.net/5n5vk/3/

40
TwystO

Ne citez pas l'expression régulière lorsque vous spécifiez une expression régulière dans js. La barre oblique suffit.

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

Regex incomplète

Il est incomplet car il correspond à une date non valide telle que 2013-99-99T04:13:00+00:00.

Meilleure solution

Le regex ci-dessous ne correspondra pas à ce type de date invalide (cf. Validation de date ISO 8601 qui ne suce pas ). Vous pouvez tester avec le code suivant:

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]); }
}
60
Édouard Lopez

J'ai trouvé le RegExp qui essaie également de valider la date un peu exagéré pour moi. Je voulais juste savoir si une chaîne contient une chaîne de date ISO 8601. Je vérifierai si la date est réellement valide après l'avoir convertie en objet Date .

Voici 2 versions du RegExp. Cela vérifie d'abord si la chaîne est une chaîne de date ISO 8601 valide. Les autres tests pour une chaîne de date complète, y compris les heures/minutes/secondes (couramment utilisé dans les 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
25
SnailCrusher

JavaScript date.toISOString () regex

Cela tente uniquement de résoudre le modèle de base de 2017-06-17T00:00:00.000Z que vous attendez de Javascript.

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

L'une des choses les plus ennuyeuses à propos de JSON est qu'on ne peut pas simplement passer une date et s'attendre à ce qu'elle se convertisse correctement. Étant donné que la plupart des gens utilisent JavaScript, cela est probablement pratique.

Voici un extrait de démonstration si vous devez passer à mongo et devez le convertir.

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

Je soutiens que c'est une meilleure approche car vous pouvez être assuré que la date sera analysée, alors vous pouvez vérifier la plage souhaitée, le tout étant assez simple et facile à entretenir, car l'expression régulière est excellente mais au point.

5
Jason Sebring

Que diriez-vous de tester uniquement si vous pouvez créer un objet Date de la chaîne, si tel est le but du test?

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

Pour ajouter à toutes ces bonnes réponses, j'ai trouvé que celle-ci fonctionnait assez bien pour les dates ISO uniquement (pas de temps)

(?: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 = réussir x = ne pas réussir)

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
0
stallingOne