Moment: Ungültige Laufzeiten unterstützen

Erstellt am 28. Juli 2014  ·  44Kommentare  ·  Quelle: moment/moment

Es gibt derzeit keine Möglichkeit, festzustellen, ob eine Daueranalyse erfolgreich war, auch nicht durch Überprüfen der Felder.

New Feature

Hilfreichster Kommentar

Gibt es hierzu Updates?

Mit moment 2.23.0 die Funktion isValid() auch true wenn versucht wird, eine Dauer aus einem ungültigen ISO8601-String zu erstellen.

Beispiel:

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

Es ist irgendwie nervig imo. und verfehlt den Zweck der isValid() Funktion für Duration Objekte vollständig (gibt es überhaupt einen Fall, wenn isValid() false zurückgibt, da der Moment sogar ein ungültiges interpretiert Eingang?)

Alle 44 Kommentare

Ich stimme zu. Wir brauchen eine isValid-Methode als Start.

Ich denke, dass ungültige Dauern Ausnahmen auslösen sollten, und die derzeitige Behandlung ungültiger Dauern ist ein Fehler und keine Verbesserung. Betrachten Sie diese Fälle:

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

Was wird das Ergebnis sein? Die Dokumente definieren nicht, was bei einer schlechten Eingabe passiert.

Dies hat einen kaskadierenden Effekt, da duration anstelle von add() und subtract() , sodass diese ebenfalls undefiniertes Verhalten haben:

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

Aus manuellen Tests kann ich Ihnen sagen, was passiert: moment "erfolgt" mit einer Dauer von Null.

Wenn moment() einfach eine Ausnahme bei fehlerhafter Eingabe ausgelöst hätte, wäre dieses Problem sofort erkannt worden. Da es stillschweigend "erfolgreich" war, blieb ein Fehler der Klasse Garbage-In, Garbage-Out bestehen.

Da das Verhalten der Dauer von Tippfehlern derzeit nicht definiert ist, wäre es abwärtskompatibel, Ausnahmen für fehlerhafte Zeichenfolgen auszulösen.

Wenn eine nicht vertrauenswürdige Zeichenfolge verwendet wird, die möglicherweise einen Tippfehler enthält, kann try/catch explizit verwendet werden, wenn getestet wird, ob die Zeichenfolge verwendet werden kann, um eine gültige Dauer zu beschreiben.

+1 @markstos.

Wie wäre es mit der Unterstützung einer strict Option (wie der Moment selbst für Daten), die wirft? Das Zurückgeben einer Dauer von Null, wenn das Parsen fehlschlägt, ist ziemlich gefährlich.

Eine Option strict wäre besser als keine Änderung, aber ich glaube nicht, dass das Analysieren ungültiger Daten als Null-Dauer überhaupt ein gutes Standardverhalten ist.

Einverstanden. Würde ein möglicher Wechsel erst bei [email protected] landen?

Warum nicht das gleiche Muster wie im Rest des Augenblicks verwenden? Verwenden Sie ein _isValid-Feld und eine isValid()-Methode und legen Sie eine Dauer als ungültig fest, wenn die Analyse fehlschlägt.

Als Referenz sind hier die anderen dokumentierten Stellen, an denen isValid() verwendet wird:

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

Das Verlinken auf die Dokumentation und nicht auf den Code war beabsichtigt, obwohl die Codeerwähnungen ebenfalls relevant sind.

+1
Eine Fähigkeit, herauszufinden, ob das Parsing erfolgreich war oder nicht, ist dringend erforderlich.
Wenn Abwärtskompatibilität ein Problem ist, könnte es möglich sein, eine Methode Duration.parse(input: string, strict?: boolean = true): Duration einzuführen, die ausgelöst wird, wenn die Eingabe falsch ist und das Argument strict angegeben wurde.
Das aktuelle Verhalten, wenn wir eine Duration mit allen Nullen für beliebige Daten erhalten, ist sehr seltsam.

+1
Eine isValid()-Methode für eine Dauer zu haben (um zu sehen, ob das Parsen erfolgreich war) wäre praktisch

Hallo zusammen, Moment 2.18.0 hat jetzt eine .isValid Methode für Dauern. Es ist jedoch ziemlich nachsichtig. @markstos @theazureshadow und andere, probiere es aus und lass es uns wissen, wenn du Vorschläge hast.

@marwahaha ,

Als ersten Test habe ich eines der obigen Beispiele kopiert/eingefügt. Anstatt wie erwartet true oder false zurückzugeben, wird eine Ausnahme ausgelöst (mit Moment 2.18.0):

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

(Die ungültige Dauer wurde immer noch "erfolgreich" erstellt, ohne eine Ausnahme auszulösen, aber jetzt zu prüfen, ob sie gültig ist, löst eine Ausnahme aus!)

Obwohl es anscheinend noch keine Dokumentation für die neue Methode gibt, ist dies möglicherweise nicht die beabsichtigte Verwendung.

@markstos Ich habe diesen Code gerade in der Konsole von Momentjs.com - die 2.18.0 hat - ohne Probleme ausgeführt. Können wir dazu mehr Details erfahren?

Vielleicht sollte dieser Code ungültig sein, weil Minuten falsch geschrieben sind.

Am 21. März 2017 um 14:35 Uhr schrieb "Maggie Pint" [email protected] :

@markstos https://github.com/markstos Ich habe gerade diesen Code in der ausgeführt
Konsole von Momentjs.com - die 2.18.0 hat - ohne ein Problem. Können wir bekommen
mehr Details dazu?


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/moment/moment/issues/1805#issuecomment-288176838 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/ACbGmWIf24KlRs8oiS2wTn206iJNMod7ks5roBhfgaJpZM4CRuVM
.

@maggiepint @marwahaha Ja, die falsche Schreibweise von „Minuten“ Deshalb sollte die Dauer ungültig.

@markstos Ich kann diese Ausnahme auch in der Konsole von Momentjs.com nicht reproduzieren. (Das ist jetzt jedoch 2.18.1.) Wenn Sie die Ausnahme beim Aufruf von isValid immer noch reproduzieren können, können wir weitere Details erfahren?

screen shot 2017-03-22 at 10 38 06

(Offensichtlich wollte Mark, dass isValid in dieser Situation false zurückgibt, aber das ist ein separates Problem von der Ausnahme. Es ist für mich nicht 100% offensichtlich, wie wir mit der Parsing-Gültigkeit mit Objekteingaben umgehen sollen.)

Ich kann die Ausnahme auch mit 2.18.1 nicht reproduzieren. Vielleicht war es ein Fehlalarm. Ich kann das Ergebnis von @butterflyhug reproduzieren, dass diese Art von ungültiger Dauer "true" für "isValid()" zurückgibt.

Sollte das Parsen in diesem Fall nicht fehlschlagen, anstatt als Ergebnis "0 Minuten" als falsch gültige Ausgabe zurückzugeben?

Sollte eine andere Frage sein, aber IIRC interpretiert das
Wert in Millisekunden, da die Einheit nicht in der Hashtabelle der Einheit gefunden wird.

Sollte es ungültig sein? IMO wahrscheinlich.

Am 22. März 2017, 8:42 Uhr, schrieb "Mark Stosberg" [email protected] :

Ich kann die Ausnahme auch mit 2.18.1 nicht reproduzieren. Vielleicht war es falsch
Alarm. Ich kann @butterflyhug https://github.com/butterflyhug reproduzieren
Ergebnis dieser Art von ungültiger Dauer, die "true" zurückgibt für
"ist gültig()".

Sollte in diesem Fall das Parsen nicht fehlschlagen, anstatt "0 Minuten" als a . zurückzugeben
falsch gültige Ausgabe als Ergebnis?


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/moment/moment/issues/1805#issuecomment-288440827 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AFxi0nZAz8gwAJM8fVx5rYPyIWjeEfHMks5roUF4gaJpZM4CRuVM
.

Hier scheint ein Bug vorzuliegen:

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

Es wird davon ausgegangen, dass dort die Zeichenfolge gültig ist und in der "Dauer"-Map erscheint. Es scheint, als ob die Lösung darin besteht, hier eine Überprüfung hinzuzufügen, um zu bestätigen, dass die Zeichenfolge ein gültiger Wert ist, der festgelegt werden soll. Wenn nicht, setze _isValid:false

Dieses Verhalten entspricht der Standardmethode isValid :

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

Die Quelle dafür ist normalizeObjectUnits https://github.com/moment/moment/blob/497f918515ae6ab900f008f19523b1e4ae5e2450/src/lib/units/aliases.js#L14 -L29, das nur gültige Attribute hinzufügt (und die beleidigenden löscht) Einsen).

@maggiepint @ichernev sollte sich dieses Verhalten ändern? Wir machen bald ein Breaking Release...

Das Konvertieren von '3 Minuten' in '0 Minuten' und das Deklarieren des Ergebnisses als "gültig" ist ein Fehler. Es kann eine bahnbrechende Änderung sein, es zu beheben, aber es ist immer noch eine Fehlerbehebung.

Ich stimme zu, dass dieses Validierungsverhalten nicht ideal ist, aber ich bin nicht der Meinung, dass dies unbedingt ein Fehler ist .

Betrachten Sie den Fall, in dem Sie etwas wie moment({'minutes': 3, '$cacheKey': 92619502}).isValid() analysieren. Ich erwarte stark, dass wir Benutzer haben, die diese Analyse als gültigen Moment schätzen, und ich sehe keinen prinzipiellen Unterschied zwischen diesem Beispiel und dem von Ihnen geschriebenen Fehler.

Die API, über die wir diskutieren, ist "Objekt-Parser" für den moment Konstruktor, der hier dokumentiert ist:

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

Die Dokumentation schweigt derzeit über die Behandlung von unbekannten oder zusätzlichen Argumenten.

Momentan kann das Verhalten von Moment hier als "Garbage In, Garbage Out" beschrieben werden. Die Mülleingabe wird stillschweigend akzeptiert und das Ergebnis ist "Müll raus"-- falsch geschriebene Daten werden in andere Daten umgewandelt und als gültig betrachtet!

Diese Updates würden es einem Entwickler ermöglichen, so schnell wie möglich herauszufinden, dass er einen Fehler gemacht hat:

  • Dokument, dass eine Ausnahme in unbekannten Argumenten ausgelöst wird, wird an den Objektkonstruktor übergeben.

    • Eine Ausnahme auslösen, wenn unbekannte Argumente an den Objektkonstruktor übergeben werden

Solange Moment "Garbage In" weiterhin als gültig akzeptiert, wird dies weiterhin ein Bärendienst für Entwickler sein und Benutzer müssen mit Moment fälschlicherweise melden, dass fehlerhafte Daten "gültig" sind.

Diese Verbesserung scheint eine "bahnbrechende" Änderung wert zu sein.

Ich wurde gerade davon gebissen: moment().subtract('1 day') ... dies ist keine gültige Art, eine Dauer auszudrücken. Ich würde jedoch nicht erwarten, dass es .subtract(0) . IMO, das am wenigsten überraschende ist in diesem Fall zu werfen.

@johnvh Ich stimme voll und ganz zu.

Sie wissen, dass es keine "gültige Methode zum Ausdrücken einer Dauer" ist, aber Sie schreiben diesen Code trotzdem? Was erwartest du? Ich nehme an, Sie haben herausgefunden, dass es keine gültige Möglichkeit war, eine Dauer aus der hervorragenden Dokumentation auszudrücken, die momentjs-Autoren zur Verfügung stellen?

Am 25.04.2017 um 08:29 schrieb Mark Stosberg [email protected] :

@johnvh Ich stimme voll und ganz zu.


Sie erhalten dies, weil Sie diesen Thread abonniert haben.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub an oder schalten Sie den Thread stumm.

@simonfox- Entwickler sind Menschen. Wir machen Fehler. Deshalb besteht die Hälfte unserer Codebasis aus Tests. Die Moment-Dokumentation /ist/ ausgezeichnet, aber es hilft nicht, wenn Sie glauben, sich an die API richtig erinnert zu haben und nicht auf die Dokumentation verweisen müssen. Aus diesem Grund ist es hilfreich, nicht nur eine großartige Dokumentation zu haben, sondern auch Code, der bei ungültigen Eingaben fehlschlägt, anstatt ungültige Eingaben stillschweigend in fehlerhafte "gültige" Eingaben umzuwandeln. Wenn @johnvh beim

@markstos genau. Ich stimme zu 100% zu%.

Dies war ein Fehler, der aufgespürt werden musste. Wir haben es nicht so geschrieben, weil wir wussten, dass es natürlich ungültig ist. Es sieht richtig aus, da Manipulationsmethoden im Moment sehr liberal in ihren unterstützten Signaturen sind. Wir verwenden im selben Projekt auch Agenda , das menschliche Intervalle verwendet, um natürliche Sprache in Dauern umzuwandeln. Also werden wir so etwas haben, nur Zeilen auseinander:

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

Letzteres funktioniert wie gewünscht, ersteres nicht. Hätte ersterer eine Ausnahme ausgesprochen, hätte uns das auf unseren Fehler aufmerksam gemacht.

Außerdem impliziert die Tatsache, dass Moment /hat/ eine isValid()-Methode, dass Werte entweder als gültig oder ungültig validiert werden. In Fällen, in denen ungültige Werte als gültig klassifiziert werden, scheint die Methode isValid() nicht wie dokumentiert zu funktionieren.

Hallo zusammen, wir würden gerne alle PRs in diesem Bereich überprüfen!

Ich bin auf diesen Fehler oder ähnliches gestoßen. Wenn ich moment.duration('3', 'minutes').asMinutes() mit Moment 2.18.1 ausführe, erhalte ich ein Ergebnis von 0. Ich denke, das sollte entweder 3 zurückgeben oder eine Ausnahme auslösen. Zumindest moment.duration('3', 'minutes').isValid() sollte false .

Die Art und Weise, wie sich Moment jetzt verhält, kann eine Menge Ärger verursachen, indem Fehler verursacht werden, die möglicherweise schwer zu erkennen und zu diagnostizieren sind, wie mehrere Leute hier erwähnt haben.

Wurde dies angesprochen?

@TomJSmith Ein kurzer Test zeigt, dass der Fehler noch existiert. Dieser Code:

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

"Erfolg", subtrahiert null Tage statt wie erwartet einen Tag. Sie können .isValid() am resultierenden Datum anrufen und eine true Antwort erhalten, die anzeigt, dass das Ergebnis gültig ist, wenn es nicht gültig ist.

Aktuelles Verhalten kann in einigen Anwendungsfällen zu schlimmen Konsequenzen führen und sollte mit einer Warnung klar dokumentiert werden:

Anwendungsfall
Ich möchte Ressourcen basierend auf einer Aufbewahrungsdauer löschen:

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

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

Ergebnis:

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

Folge:
Alle Ressourcen bis zum aktuellen Datum werden gelöscht...

Bisher habe ich die einzige Möglichkeit gefunden, dies zu umgehen, wenn ich den Wert nach dem Parsen testen möchte:

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

Ja, dieser Fehler ist schlimm und seit 2014 offen. Das ist etwas, was die "date-fns"-Projekte richtig machen. Sie sagen Ihnen tatsächlich, ob eine ungültige Eingabe ungültig ist. https://date-fns.org/ Leider verarbeitet date-fns keine Zeitzonenkonvertierungen, aber vielleicht gibt es eine Möglichkeit, diese mit einer externen Bibliothek zu verarbeiten.

Damit das Moment-Projekt dies beheben kann, müssen sie aufhören, Mülleingaben zu akzeptieren und sie als gültiges Datum zu behandeln. Obwohl dies ein besseres Verhalten zu sein scheint, handelt es sich technisch gesehen um eine Änderung des "Rückwärtsbruchverhaltens", sodass es anscheinend Widerstand gibt, die Änderung vorzunehmen. Aber da das Projekt in den letzten fast vier Jahren keine Maßnahmen ergriffen hat, würde ich nicht mit einer baldigen Lösung rechnen.

Gibt es hierzu Updates?

Mit moment 2.23.0 die Funktion isValid() auch true wenn versucht wird, eine Dauer aus einem ungültigen ISO8601-String zu erstellen.

Beispiel:

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

Es ist irgendwie nervig imo. und verfehlt den Zweck der isValid() Funktion für Duration Objekte vollständig (gibt es überhaupt einen Fall, wenn isValid() false zurückgibt, da der Moment sogar ein ungültiges interpretiert Eingang?)

@robbiecloset Das Update ist seit meinem letzten Post im April, das Projekt "date-fns" hat sich bei der Zeitzonenunterstützung verbessert. Dabei helfen jetzt die Projekte "date-fns-timezone" und "date-fns-tz".

Ich würde es in Betracht ziehen, es zu verwenden, wenn es machbar ist, zu wechseln.

Ich verwende moment.duration(value).toISOString() === value , dieser Wert wird aus einer Konfiguration gelesen.

Ich verwende moment.duration(value).toISOString() === value, dieser Wert wird aus einer Konfiguration gelesen.

@bors-ltd Ich denke, ein Teil des Problems besteht darin, dass der Moment möglicherweise zwei Werte decodieren kann, die denselben codierten Wert erzeugen.

Beispiel: moment.duration('PT0M0S').toISOString() === moment.duration('PT0S').toISOString() .

Wenn Sie sich die Tests ansehen, scheint es, als ob ungültige Werte tatsächlich Teil der Spezifikation sind:

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

Muster, die nicht dem ISO-Dauerstandard entsprechen, werden als "0" Sekunden getestet.

Hallo, wir hatten auch das gleiche Problem mit der Methode isValid() und haben es am Ende manuell gemacht.
const isValidDuration = duration => { return !!duration.match( /^(-?)P(?=\d|T\d)(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)([DW]))?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/ ); };
Hoffe es konnte jedem helfen.

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

Danke für die ganze Diskussion hier.

Ein Hacky-Fix ​​besteht darin, die isValid-Methode durch eine Methode zu ersetzen, die sicherstellt, dass die Summe der Datenteile > 0 (oder zumindest wahrscheinlich ungültig) ist.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen