Moment: isSameOrAfter gibt eine zufällige Ausgabe beim Vergleichen von moment() mit moment()

Erstellt am 21. Feb. 2017  ·  4Kommentare  ·  Quelle: moment/moment

Beschreibung
Also haben ich und ein Kollege einen Fehler in unserem Code gefunden, der dadurch verursacht wurde, dass wir eine undefinierte Variable verwendet haben (im Grunde moment(undefined) und dann versucht haben, dies mit einer neuen Momentinstanz zu vergleichen ( moment() ) mit der Methode isSameOrAfter .

Was wir im Grunde genommen haben, war Folgendes:

let isSame = moment(undefined).isSameOrAfter(moment());

Wenn Sie diesen Code ein- oder zweimal ausführen, wird true , aber nicht immer. Hin und wieder gibt es false , ich denke, es liegt daran, dass das Erstellen von zwei Instanzen von Momenten nacheinander ohne definierte Zeit diese mit einem Unterschied von wenigen Mikrosekunden erzeugen könnte.

Hier ist ein Test, den ich sowohl in Node v7.1.0 unter Windows 10 als auch in Chrome/56.0.2924.87 mit Moment.js 2.17.1 ausgeführt habe.

const moment = require('moment');

function isSameOrAfter() {
    console.log('isSameOrAfter')
    for (let i = 0; i < 1000; i++) {
        let output = moment().isSameOrAfter(moment());
        if (!output) {
            console.log(output, i);
        }
    }
}

function isSame() {
    console.log('isSame')
    for (let i = 0; i < 1000; i++) {
        let output = moment().isSame(moment());
        if (!output) {
            console.log(output, i);
        }
    }
}

function sameExactVariable() {
    console.log('Another test comparing the same exact variable')
    for (let i = 0; i < 1000; i++) {
        const now = moment();
        let output = now.isSame(now);
        if (!output) {
            console.log(output, i);
        }
    }
}

isSameOrAfter();
isSame();
sameExactVariable();

Die ersten beiden Funktionen protokollieren false einige Male von 1000, und die dritte Funktion nicht. Es wird nur protokolliert, wenn eine Ausnahme auftritt.

Umfeld:
Di 21 Feb 2017 14:36:06 GMT+0100 (W. Europa Standardzeit)
2017-02-21 14:36:06
-60
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, wie Gecko) Chrome/56.0.2924.87 Safari/537.36
2.17.1

Hilfreichster Kommentar

@imrvshah Beachten

...isSameOrAfter(moment().format('MM-DD-YYYY'))

erstellt einen neuen Moment mit der aktuellen Uhrzeit, formatiert ihn als String und übergibt diesen String an isSameOrAfter() , der ihn erneut analysiert. Du hättest einfach sagen sollen:

...isSameOrAfter(moment())

Und den Moment gespeichert -> String -> Momentarbeit. Das ist viel besserer Code, aber ich würde auch wetten, dass er den Fehler behebt. Haben Sie Warnungen zu veralteten Versionen bemerkt, die sagen: "Hey, Sie sollten keine Zeichenfolgen an solche Momente weitergeben"? Moment weiß, wie man ISO 8601-Strings wie moment("1982-05-25") analysiert. Es kann auch Strings analysieren, bei denen das Format angegeben ist, z. B. moment("05-25-1982", "MM-DD-YYYY") . Aber es hat keine Ahnung, dass eine Zeichenfolge wie "05-25-1982" "MM-DD-YYYY" sein soll, ohne dass Sie es sagen. Es lässt den Browser also raten, indem es einfach diese Zeichenfolge an den Date Konstruktor übergibt. Mit anderen Worten, Ihr Code wird wie folgt entpackt:

m.isSameOrAfter("05-25-1982");
m.isSameOrAfter(moment("05-25-1982"))
m.isSameOrAfter(moment(new Date("05-25-1982")))

Es gibt einen Grund, warum wir das nicht mehr empfehlen: Es liefert inkonsistente Ergebnisse, je nachdem, welcher Browser es ausführt. Worauf Sie also stoßen, ist, dass iOS dieses Format nicht nativ unterstützt. In meiner Safari-Entwicklerkonsole:

> new Date("05-25-1982")
Invalid Date

Das gab Ihnen schlechte Vergleiche, die Sie mit einem leeren Array zurückließen.

Alle 4 Kommentare

Wahrscheinlich habe ich das gleiche Problem. Es funktioniert wie erwartet auf Chrome- und Android-Geräten, aber nicht unter iOS.

let arrDates: Array<String> = []; _.each(Dates, (date) => { if (moment(date).isSameOrAfter(moment().format('MM-DD-YYYY'))) { arrDates.push(date); } });

In iOS erhalte ich das Array null, während es auf Chrome und Android funktioniert.

Umfeld:

Cordova CLI: 6.4.0
Ionic Framework-Version: 2.0.0
Ionische CLI-Version: 2.1.18
Ionic App Lib Version: 2.1.9
Ionische App-Skripte Version: 1.0.0
iOS-Bereitstellungsversion: 1.9.0
iOS-Sim-Version: 5.0.13
Betriebssystem: macOS Sierra
Knotenversion: v6.9.2
Xcode-Version: Xcode 8.2.1 Build-Version 8C1002

@ErikMartensson

Ich denke, es liegt daran, dass das Erstellen von zwei Instanzen von Momenten nacheinander ohne definierte Zeit diese mit einem Unterschied von wenigen Mikrosekunden erzeugen könnte.

Ja, moment() oder moment(undefined) – die identisch sind – bedeutet jetzt . JS-Daten haben eine Auflösung von Millisekunden, wenn also jetzt eine andere Millisekunde ist, was manchmal vorkommt, dann kommt ein Mal nach dem anderen. AFAIK, JS definiert nicht, in welcher Reihenfolge moment().isSameOrAfter(moment()) diese beiden moment() Aufrufe auswertet. Aber da es offensichtlich sowieso den zweiten Aufruf machen muss, bevor isSameOrAfter() wird, würde es mich nicht überraschen, wenn der zweite in der Praxis immer zuerst kommt. Das würde bedeuten, dass bei einem Zeitunterschied auch der "orAfter"-Teil des Tests fehlschlägt. Sie könnten dies mit einem Debugger bestätigen.

Ich weiß nicht, was ich dir sagen soll. So müssen Datumsangaben mit endlicher Auflösung funktionieren; "jetzt" bedeutet eine andere Zeit, je nachdem, wann Sie es sagen.

@imrvshah Beachten

...isSameOrAfter(moment().format('MM-DD-YYYY'))

erstellt einen neuen Moment mit der aktuellen Uhrzeit, formatiert ihn als String und übergibt diesen String an isSameOrAfter() , der ihn erneut analysiert. Du hättest einfach sagen sollen:

...isSameOrAfter(moment())

Und den Moment gespeichert -> String -> Momentarbeit. Das ist viel besserer Code, aber ich würde auch wetten, dass er den Fehler behebt. Haben Sie Warnungen zu veralteten Versionen bemerkt, die sagen: "Hey, Sie sollten keine Zeichenfolgen an solche Momente weitergeben"? Moment weiß, wie man ISO 8601-Strings wie moment("1982-05-25") analysiert. Es kann auch Strings analysieren, bei denen das Format angegeben ist, z. B. moment("05-25-1982", "MM-DD-YYYY") . Aber es hat keine Ahnung, dass eine Zeichenfolge wie "05-25-1982" "MM-DD-YYYY" sein soll, ohne dass Sie es sagen. Es lässt den Browser also raten, indem es einfach diese Zeichenfolge an den Date Konstruktor übergibt. Mit anderen Worten, Ihr Code wird wie folgt entpackt:

m.isSameOrAfter("05-25-1982");
m.isSameOrAfter(moment("05-25-1982"))
m.isSameOrAfter(moment(new Date("05-25-1982")))

Es gibt einen Grund, warum wir das nicht mehr empfehlen: Es liefert inkonsistente Ergebnisse, je nachdem, welcher Browser es ausführt. Worauf Sie also stoßen, ist, dass iOS dieses Format nicht nativ unterstützt. In meiner Safari-Entwicklerkonsole:

> new Date("05-25-1982")
Invalid Date

Das gab Ihnen schlechte Vergleiche, die Sie mit einem leeren Array zurückließen.

@icambron

Ich stimme Ihnen zu und finde in einer Konsole heraus, dass es sich um eine veraltete Warnung aufgrund des Datumsformats handelt.

Vielen Dank für Ihren Kommentar, dass Sie es nicht mehrmals einpacken und einfach verwenden. ...isSameOrAfter(moment())

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

vbullinger picture vbullinger  ·  3Kommentare

M-Zuber picture M-Zuber  ·  3Kommentare

tanepiper picture tanepiper  ·  3Kommentare

slavafomin picture slavafomin  ·  3Kommentare

RobinvanderVliet picture RobinvanderVliet  ·  3Kommentare