Moment: Prise en charge des durées invalides

Créé le 28 juil. 2014  ·  44Commentaires  ·  Source: moment/moment

Il n'existe actuellement aucun moyen de déterminer si une analyse de durée a réussi, même en inspectant les champs.

New Feature

Commentaire le plus utile

Y a-t-il des mises à jour à ce sujet ?

Avec moment 2.23.0 la fonction isValid() renvoie également true lors de la tentative de création d'une durée à partir d'une chaîne ISO8601 invalide.

Exemple:

const mom = moment.duration('asdf')
console.log(mom.isValid()) // This returns true, expected would be false 

C'est un peu ennuyeux imo. et va complètement à l'encontre du but de la fonction isValid() sur les objets Duration (y a-t-il même un cas où isValid() renvoie false puisque le moment interprète même un saisir?)

Tous les 44 commentaires

Je suis d'accord. Nous avons besoin d'une méthode isValid pour commencer.

Je pense que les durées invalides devraient lever des exceptions et la gestion actuelle des durées invalides est un bogue et non une amélioration. Considérez ces cas :

`var wrong = moment.duration(3,'mintues');`

Quel sera le résultat ? Les docs ne définissent pas ce qui se passe en cas de mauvaise entrée.

Cela a un effet en cascade, car duration est utilisé à la place de add() et subtract() , donc ceux-ci ont également un comportement indéfini :

var hmm = moment().subtract(3,'mintues').toDate();
var uhoh = moment().add(3,'mintues').toDate();

À partir des tests manuels, je peux vous dire ce qui se passe : moment "réussit" en utilisant une durée de zéro.

Si moment() avait simplement levé une exception sur une mauvaise entrée, ce problème aurait été identifié immédiatement. Depuis qu'il a "réussi" en silence, un bogue de classe Garbage-In, Garbage-Out persistait.

Étant donné que le comportement de la durée saisie est actuellement indéfini, commencer à lever des exceptions sur des chaînes incorrectes serait rétrocompatible.

Si une chaîne non fiable est utilisée et peut contenir une faute de frappe, try/catch peut être utilisé explicitement lors du test si la chaîne peut être utilisée pour décrire une durée valide.

+1 @markstos.

Qu'en est-il de la prise en charge d'une option strict (comme le moment lui-même pour les dates) qui lance ? Renvoyer une durée de zéro lorsque l'analyse échoue est assez dangereux.

Une option strict serait mieux que pas de changement, mais je ne pense pas que l'analyse des dates invalides car la durée zéro est un bon comportement par défaut en premier lieu.

D'accord. Un éventuel changement n'arriverait-il qu'avec

Pourquoi ne pas utiliser le même motif que le reste du moment ? Ayez un champ _isValid et une méthode isValid() et définissez une durée comme invalide si l'analyse échoue.

Pour référence, voici les autres endroits documentés où isValid() est utilisé :

https://github.com/moment/momentjs.com/search?utf8=%E2%9C%93&q=isValid

Le lien vers la documentation et non le code était intentionnel, bien que les mentions de code soient également pertinentes.

+1
Une capacité à savoir si l'analyse a réussi ou non est très nécessaire.
Si la compatibilité descendante est un problème, il pourrait être possible d'introduire une méthode Duration.parse(input: string, strict?: boolean = true): Duration qui lancerait si l'entrée est incorrecte et que l'argument strict été spécifié.
Le comportement actuel lorsque nous obtenons une durée avec des zéros pour des données arbitraires est très étrange.

+1
Avoir une méthode isValid () sur une durée (pour voir si l'analyse a réussi) serait pratique

Salut à tous, Moment 2.18.0 a maintenant une méthode .isValid pour les durées. Cependant, c'est assez clément. @markstos @theazureshadow et autres, essayez-le et faites-nous savoir si vous avez des suggestions.

@marwahaha ,

Comme test initial, j'ai copié/collé l'un des exemples ci-dessus. Au lieu de renvoyer true ou false comme prévu, il lève une exception (avec le moment 2.18.0) :

 moment.duration(3,'mintues').isValid();

(Créé la durée invalide "réussit" toujours sans lever d'exception, mais maintenant vérifier si elle est valide lève une exception!)

Bien qu'il semble qu'il n'y ait pas encore de documentation pour la nouvelle méthode, ce n'est peut-être pas l'utilisation prévue.

@markstos Je viens d'

Peut-être que ce code devrait être invalide car les minutes sont mal orthographiées.

Le 21 mars 2017 à 14 h 35, "Maggie Pint" [email protected] a écrit :

@markstos https://github.com/markstos Je viens d' exécuter ce code dans le
console de Momentjs.com - qui a 2.18.0 - sans problème. Peut-on avoir
plus de détails là-dessus ?

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moment/moment/issues/1805#issuecomment-288176838 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/ACbGmWIf24KlRs8oiS2wTn206iJNMod7ks5roBhfgaJpZM4CRuVM
.

@maggiepint @marwahaha Oui, la faute d'orthographe de "minutes" EST la raison pour laquelle la durée devrait être invalide.

@markstos Je ne peux pas non plus reproduire cette exception dans la console de Momentjs.com. (C'est maintenant 2.18.1.) Si vous pouvez toujours reproduire l'exception lors de l'appel à isValid, pouvons-nous obtenir plus de détails ?

screen shot 2017-03-22 at 10 38 06

(Évidemment, Mark voulait que isValid renvoie false dans cette situation, mais c'est un problème distinct de l'exception. Ce n'est pas évident à 100% pour moi comment gérer la validité de l'analyse avec les entrées d'objet.)

Je ne peux pas non plus reproduire l'exception avec 2.18.1. C'était peut-être une fausse alerte. Je peux reproduire le résultat de @butterflyhug d'avoir ce type de durée invalide renvoyant "true" pour "isValid()".

L'analyse ne devrait-elle pas échouer dans ce cas au lieu de renvoyer "0 minute" comme résultat incorrectement valide ?

Devrait est une question différente, mais IIRC ce qu'il fait est d'interpréter que
valeur en millisecondes car l'unité n'est pas trouvée dans la table de hachage des unités.

Doit-il être invalide ? OMI probablement.

Le 22 mars 2017 à 08h42, "Mark Stosberg" [email protected] a écrit :

Je ne peux pas non plus reproduire l'exception avec 2.18.1. C'était peut-être un faux
alarme. Je peux reproduire @butterflyhug https://github.com/butterflyhug 's
résultat d'avoir ce type de durée invalide retournant "true" pour
"est valable()".

L'analyse ne devrait pas échouer dans ce cas au lieu de renvoyer "0 minutes" en tant que
résultat incorrectement valide ?

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moment/moment/issues/1805#issuecomment-288440827 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AFxi0nZAz8gwAJM8fVx5rYPyIWjeEfHMks5roUF4gaJpZM4CRuVM
.

Il semble y avoir un bug ici :

https://github.com/moment/moment/blob/497f918515ae6ab900f008f19523b1e4ae5e2450/src/lib/duration/create.js#L34

On suppose que là, la chaîne est valide et apparaît dans la carte de "durée". Il semble que le correctif consiste à ajouter une vérification ici pour confirmer que la chaîne est une valeur valide à définir. Sinon, définissez _isValid:false

Ce comportement est cohérent avec la méthode standard isValid :

moment({'mintues': 3}).isValid()
> true

La source de ceci est normalizeObjectUnits https://github.com/moment/moment/blob/497f918515ae6ab900f008f19523b1e4ae5e2450/src/lib/units/aliases.js#L14 -L29 qui ajoute uniquement des attributs valides (et supprime le ceux).

@maggiepint @ichernev ce comportement devrait-il changer ? Nous allons bientôt faire une sortie de rupture...

Convertir '3 minutes' en '0 minutes' et déclarer le résultat "valide" est un bogue. Cela peut être un changement de rupture pour le corriger, mais c'est toujours une correction de bogue.

Je suis d'accord que ce comportement de validation n'est pas idéal, mais je ne suis pas d'accord pour dire qu'il s'agit nécessairement d'un bug .

Considérez le cas où vous analysez quelque chose comme moment({'minutes': 3, '$cacheKey': 92619502}).isValid() . Je m'attends fortement à ce que nous ayons des utilisateurs qui apprécient que cette analyse soit un moment valide, et je ne vois pas de distinction de principe entre cet exemple et le bogue que vous avez écrit.

L'API dont nous discutons est un "analyseur d'objets" pour le constructeur moment , qui est documenté ici :

http://momentjs.com/docs/#/parsing/object/

La documentation est actuellement muette sur le traitement du passage d'arguments inconnus ou supplémentaires.

À l'heure actuelle, le comportement de Moment ici peut être décrit comme "Garbage In, Garbage out". L'entrée des ordures est acceptée en silence et le résultat est "Garbage out" - les dates mal orthographiées sont converties en d'autres dates et considérées comme valides !

Ces mises à jour permettraient à un développeur de découvrir dès que possible qu'il a fait une erreur :

  • Le document indiquant qu'une exception sera levée dans des arguments inconnus est transmis au constructeur d'objet.

    • Lever une exception si des arguments inconnus sont passés au constructeur d'objet

Tant que Moment continuera d'accepter "Garbage In" comme valide, cela continuera à être un mauvais service pour les développeurs et les utilisateurs se retrouveront avec Moment signalant à tort que les dates cassées sont "valides".

Cette amélioration semble bien mériter un changement "de rupture".

J'ai juste été mordu par ceci : moment().subtract('1 day') ... ce n'est pas une manière valide d'exprimer une durée. Je ne m'attendrais pas à ce que cela soit équivalent à .subtract(0) . OMI, la chose la moins surprenante à faire dans ce cas est de lancer.

@johnvh Je suis tout à fait d'accord.

Vous savez que ce n'est pas un "moyen valable d'exprimer une durée" mais vous écrivez quand même ce code ? Qu'attendez-vous? Je suppose que vous avez compris que ce n'était pas un moyen valable d'exprimer une durée à partir de l'excellente documentation fournie par les auteurs de momentjs?

Le 25/04/2017, à 08h29, Mark Stosberg [email protected] a écrit :

@johnvh Je suis tout à fait d'accord.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, affichez-le sur GitHub ou coupez le fil de discussion.

Les développeurs @johnvh avait immédiatement reçu un échec de validation lors de l'

@markstos exactement. Je suis d'accord à 100%.

C'était un bug qui devait être traqué. Nous ne l'avons pas écrit de cette façon sachant qu'il était invalide bien sûr. Cela semble juste, car les méthodes de manipulation du moment sont très libérales dans leurs signatures prises en charge. Nous utilisons également agenda dans le même projet, qui utilise l'intervalle humain pour convertir le langage naturel en durées. Nous aurons donc quelque chose comme ça à quelques lignes de distance :

moment().subtract('1 day');
agenda.processEvery('1 day');

Ce dernier fonctionne comme prévu, pas le premier. Si le premier avait soulevé une exception, cela nous aurait alerté de notre erreur.

De plus, le fait que Moment /a/ une méthode isValid() implique qu'elle valide les valeurs comme valides ou non valides. Dans les cas où des valeurs non valides sont classées comme valides, la méthode isValid() semble ne pas fonctionner comme indiqué.

Salut à tous, nous serions ravis d'examiner les relations publiques dans ce domaine !

J'ai rencontré ce bug, ou quelque chose de similaire. Si j'exécute moment.duration('3', 'minutes').asMinutes() utilisant Moment 2.18.1, j'obtiens un résultat de 0. Je pense que cela devrait soit renvoyer 3, soit lever une exception. À tout le moins, moment.duration('3', 'minutes').isValid() devrait renvoyer false .

La façon dont Moment se comporte maintenant peut causer beaucoup de problèmes en provoquant des bogues qui peuvent être difficiles à détecter et à diagnostiquer, comme plusieurs personnes ici l'ont mentionné.

Cela a-t-il été abordé ?

@TomJSmith Un test rapide montre que le bogue existe toujours. Ce code :

 moment().subtract('1 day');

"réussi", en soustrayant zéro jour au lieu d'un jour comme prévu. Vous pouvez appeler .isValid() à la date résultante et obtenir une réponse true indiquant que le résultat est valide alors qu'il ne l'est pas.

Le comportement actuel peut entraîner de mauvaises conséquences dans certains cas d'utilisation et doit être clairement documenté par un avertissement :

Cas d'utilisation
Je souhaite supprimer des ressources en fonction d'une durée de conservation :

const duration = moment.duration('invalid');
const currentDate = moment();
const removeBeforeDate  = moment().subtract(duration);

console.log(`currentDate      : ${currentDate}`);
console.log(`removeBeforeDate : ${removeBeforeDate}`);

Résultat:

currentDate      : Fri Apr 13 2018 13:15:04 GMT+0200
removeBeforeDate : Fri Apr 13 2018 13:15:04 GMT+0200

Conséquence:
Toutes les ressources jusqu'à la date actuelle sont supprimées...

Jusqu'à présent, la seule façon que j'ai trouvée de contourner ce problème est de tester la valeur après l'analyse :

const duration = moment.duration('invalid');
if (duration.toISOString() === 'P0D') {
    // throw an Error
}

Oui, ce bug est mauvais et est ouvert depuis 2014. C'est quelque chose que les projets "date-fns" réussissent. Ils vous disent en fait si une entrée invalide est invalide. https://date-fns.org/ Malheureusement, date-fns ne gère pas les conversions de fuseau horaire, mais il existe peut-être un moyen de les gérer avec une bibliothèque externe.

Pour que le projet Moment corrige cela, ils doivent cesser d'accepter les entrées de déchets et les traiter comme une date valide. Bien que cela semble être un meilleur comportement, il s'agit techniquement d'un changement de "comportement en marche arrière", il semble donc qu'il y ait une résistance pour effectuer le changement. Mais étant donné que le projet n'a pas pris de mesures au cours des quatre dernières années, je ne m'attendrais pas à une solution de sitôt.

Y a-t-il des mises à jour à ce sujet ?

Avec moment 2.23.0 la fonction isValid() renvoie également true lors de la tentative de création d'une durée à partir d'une chaîne ISO8601 invalide.

Exemple:

const mom = moment.duration('asdf')
console.log(mom.isValid()) // This returns true, expected would be false 

C'est un peu ennuyeux imo. et va complètement à l'encontre du but de la fonction isValid() sur les objets Duration (y a-t-il même un cas où isValid() renvoie false puisque le moment interprète même un saisir?)

@robbiecloset La mise à jour est depuis mon dernier post en avril, le projet "date-fns" s'est amélioré au niveau de la prise en charge des fuseaux horaires. Il existe maintenant des projets "date-fns-timezone" et "date-fns-tz" pour vous aider.

J'envisagerais de l'utiliser s'il est possible de changer.

J'utilise moment.duration(value).toISOString() === value , cette valeur est lue à partir d'une configuration.

J'utilise moment.duration(value).toISOString() === value, cette valeur est lue à partir d'une configuration.

@bors-ltd Je pense qu'une partie du problème est que ce moment pourrait être capable de décoder deux valeurs qui produisent la même valeur codée.

Par exemple : moment.duration('PT0M0S').toISOString() === moment.duration('PT0S').toISOString() .

Si vous regardez les tests, il semble que les valeurs invalides soient en fait en dehors de la spécification :

https://github.com/moment/moment/blob/2.24.0/src/test/moment/duration.js#L419 -L420

Les modèles qui ne correspondent pas à la norme de durée ISO sont testés comme étant « 0 » secondes.

Bonjour, nous avons également eu le même problème avec la méthode isValid() et finissons par le faire manuellement.
const isValidDuration = duration => { return !!duration.match( /^(-?)P(?=\d|T\d)(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)([DW]))?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/ ); };
J'espère que cela pourra aider quelqu'un.

Voir https://momentjs.com/docs/#/ -project-status/

Merci pour toutes les discussions ici.

Un correctif consiste à remplacer la méthode isValid par une méthode qui garantit que la somme des parties de données est > 0 (ou au moins probablement invalide)

Cette page vous a été utile?
0 / 5 - 0 notes