Moment: endOf('day') schlägt an Tagen fehl, die nicht um Mitternacht beginnen

Erstellt am 20. Apr. 2016  ·  15Kommentare  ·  Quelle: moment/moment

Erwägen:

moment("2016-10-16").endOf('day').format("YYYY-MM-DD HH:mm:ss")

In den meisten Zeitzonen wird "2016-10-16 23:59:59" . In Brasilien wird dies jedoch "2016-10-17 00:59:59" . Dies ist falsch, da nur die Stunde von 00:00 bis 00:59 am 16.10.2016 fehlt. Das Ende des 2016-10-16 ist immer noch 23:59:59 am selben Tag.

Dies ist auch mit moment-timezone reproduzierbar:

moment.tz("2016-10-16","America/Sao_Paulo").endOf('day').format("YYYY-MM-DD HH:mm:ss")

Das Problem liegt in der Methode endOf . Um das Ende des Tages zu berechnen, nehmen wir den _Start_ des Tages, addieren einen Tag und subtrahieren dann eine Millisekunde. Diese Logik ist fehlerhaft, wenn der Tag nicht um Mitternacht beginnt. Anstatt einen Tag hinzuzufügen, müssen wir die genaue Dauer des jeweiligen Tages hinzufügen.

Bug DST

Alle 15 Kommentare

Dies wurde ursprünglich als moment/moment-timezone#327 gemeldet.

2749 ist verwandt, aber etwas anders.

Im Gegensatz zur Berechnung der genauen Tageszeit können Sie nicht einfach Folgendes tun:

moment('2016-10-16').startOf('day').add(1, 'day').startOf('day').subtract(1, 'millisecond').format()
"2016-10-16T23:59:59-02:00"

Funktioniert auch am 15. gut, wenn er auch in den 16. geschoben wird:

moment('2016-10-15').startOf('day').add(1, 'day').startOf('day').subtract(1, 'millisecond').format()
"2016-10-15T23:59:59-03:00"

Gibt es einen Randfall, an den ich nicht denke?

Ich nehme an, es könnte einen Leistungsvorteil haben, es anders zu machen, aber zum Teufel, Sie können es lesen!

Hmmmm, noch was faules hier:

moment.tz("2016-10-16","America/Sao_Paulo").startOf('day').add(1,'day').startOf('day').subtract(1,'ms').format()
// "2016-10-16T23:59:59-02:00"  (ok)

moment.tz("2016-10-15","America/Sao_Paulo").startOf('day').add(1,'day').startOf('day').subtract(1,'ms').format()
// "2016-10-14T23:59:59-03:00"  (wrong date)

moment.tz("2016-10-15","America/Sao_Paulo").startOf('day').add(1,'day').format()
// "2016-10-15T23:00:00-03:00"  should have skipped forward to "2016-10-16T01:00:00-02:00"

Haben wir es hier nur mit dem ganzen mehrdeutigen Browserverhalten zu tun? Oder steckt mehr dahinter?

In Chrom mit der Windows-Zeitzone von Brasillia:

moment("2016-10-15").startOf('day').format()
"2016-10-15T00:00:00-03:00"
moment("2016-10-15").startOf('day').add(1, 'day').format()
"2016-10-16T01:00:00-02:00"

In Chrome mit meiner Zeitzone mit Moment Timezone:

moment.tz("2016-10-15","America/Sao_Paulo").startOf('day').format()
"2016-10-15T00:00:00-03:00"
moment.tz("2016-10-15","America/Sao_Paulo").startOf('day').add(1, 'day').format()
"2016-10-15T23:00:00-03:00"

COOL!

Etwas mit Moment-Zeitzone? Ich kenne den Code nicht wirklich, daher ist es schwer zu sagen. Scheint aber nicht der Browser zu sein, wenn der erste funktioniert.

Ich denke, dass dies darauf zurückzuführen ist, dass die Moment-Zeitzone immer ein ungültiges Datum zurückschiebt, wenn es zu diesem Datum "hinzugefügt" wurde. Ob beabsichtigt oder zufällig bin ich mir nicht sicher.

//setting moves forward
moment.tz("2016-10-16T00:00:00","America/Sao_Paulo").format()
"2016-10-16T01:00:00-02:00"
//adding moves backward
moment.tz("2016-10-15T00:00:00","America/Sao_Paulo").add(1, 'day').format()
"2016-10-15T23:00:00-03:00"

//setting moves forward
moment.tz("2016-03-13T02:00:00","America/Chicago").format()
"2016-03-13T03:00:00-05:00"
//adding moves backward
moment.tz("2016-03-12T02:00:00","America/Chicago").add(1, 'day').format()
"2016-03-13T01:00:00-06:00"

//one more time for funzies
moment.tz("2016-03-27T01:00:00","Europe/London").format()
"2016-03-27T02:00:00+01:00"

moment.tz("2016-03-26T01:00:00","Europe/London").add(1, 'day').format()
"2016-03-27T00:00:00Z"

Ich denke, dies hat etwas damit zu tun, dass Sie versuchen, die KeepTime-Einstellung zu verwenden, wenn Sie die Zeit nicht halten können. Ich kenne diesen Code nicht gut genug, um Ihnen zu sagen, warum der Code so ist, wie er ist, aber ich weiß mit Sicherheit, dass, wenn der KeepTime-Aufruf in diesem Code 0 statt 1 wäre, alles wie erwartet ablaufen würde. Weil die Zeit läuft, wird sie nach hinten verschoben. Und halten Sie die Zeit an, es ist einfach funky mit diesem Edge-Case.

    moment.updateOffset = function (mom, keepTime) {
        var zone = moment.defaultZone,
            offset;

        if (mom._z === undefined) {
            if (zone && needsOffset(mom) && !mom._isUTC) {
                mom._d = moment.utc(mom._a)._d;
                mom.utc().add(zone.parse(mom), 'minutes');
            }
            mom._z = zone;
        }
        if (mom._z) {
            offset = mom._z.offset(mom);
            if (Math.abs(offset) < 16) {
                offset = offset / 60;
            }
            if (mom.utcOffset !== undefined) {
                mom.utcOffset(-offset, keepTime);
            } else {
                mom.zone(offset, keepTime);
            }
        }
    };

Ich weiß nicht genug über moment-timezone, um hier hilfreich zu sein, aber vielleicht ist das Ticket, warum keepTime verwendet wird, für jeden hilfreich, der nachforscht: https://github.com/moment/moment-timezone/ Ausgaben/28

https://github.com/moment/moment/pull/1564

Dies ist im Moment die letzte große Änderung der Handhabungszonen. Ich bin mir nicht sicher, ob es mit diesem Problem zusammenhängt, aber es sollte helfen.

@maggiepint kannst du das ein bisschen erklären

wird ein ungültiges Datum immer zurückschieben

Teil. Ich meine - haben wir ein Beispiel, das ein Problem mit der Moment-Zeitzone aufdeckt, oder brauchen wir nur einen intelligenten Code, um die Sommerzeit am Anfang/Ende des Tages zu erkennen und entsprechend zu behandeln. Die zweite ist mittel bis leicht. Wenn wir die Zone, die zwischen moment-tz und moment verläuft, erneut umgestalten müssen, dann ist es die Hölle – ich würde lieber auf 3.0 warten und hoffen, dass das neue Interface dieses Problem nicht hat.

@ichernev so wie der Code heute steht, haben wir in dieser einen Ausgabe zwei Probleme. Eines ist das Problem, das @mj1856 ursprünglich angesprochen hat, nämlich dass Tage, die nicht um Mitternacht beginnen, mit einem funky Tagesendewert enden. Dies ist eine Momentangelegenheit.

Die andere ist, dass die Moment-Zeitzone, wenn ein ungültiges Datum angezeigt wird, vorwärts geht, wenn dieses ungültige Datum im Konstruktor verwendet wird, aber rückwärts, wenn es zu diesem Datum "hinzugefügt" wird. Dies ist, wie es aussieht, ein Problem mit der Moment-Zeitzone und nicht dem Moment. Ich bin mir nicht sicher, wie die Zeitzonenschnittstelle das ändert - ich müsste ein bisschen darüber nachdenken.

@maggiepint danke für die klare Erklärung.

Um das Momentproblem zu beheben : endOf('day') ist ungenau -- "zielen" Sie einfach auf das Ende des Tages, gehen Sie dorthin, wenn es 00:00 ist, beenden Sie es, andernfalls zielen Sie erneut, wenn das zweite Ziel 00 erreicht: 00 wir sind fertig, ansonsten den ersten Schuss verwenden. Das zweite Ziel hilft, wenn wir über DST springen und um eine Stunde "verzerrt" werden. Wenn das Ende des Tages aufgrund der Sommerzeit eine ungültige Zeit ist, kann das zweite Ziel nicht schaden.

Wir sollten diesen Algorithmus für alle endOf , vielleicht sogar für startOf , aber das ist mit dem Setzen auf Null, das wir derzeit machen, schwieriger zu begründen.

Hallo Leute, ich bin auch von diesem Problem in der aktuellen Version von Moment (2.14.1) betroffen.

Ich habe #3716 eingereicht, um dies zu beheben, sehe jedoch derzeit Probleme mit Travis CI aus Transpilationsgründen. Werde es demnächst genauer untersuchen.

Dieser ist auch verwandt (Standard-Locale für Brasilien).

Operation ergibt das gleiche Datum:

moment("2017-10-16T00:59:59.999").subtract(1,'day').endOf('day')
=> "2017-10-16T00:59:59.999"

Hey - ich habe gerade #4164 eingereicht, was dies sowohl für startOf als auch für endOf behebt. Würde gerne Feedback dort bekommen, damit wir das hoffentlich endlich voranbringen können.

@ mj1856 , ich habe meinen PR geschlossen, da das Problem mit endOf in DST Edge behoben zu sein scheint. Könnte das auch behoben werden?

Ich habe die #4164 getestet und das sieht so aus, als ob sie darauf fixiert wäre. Warten auf Zusammenführen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

danieljsinclair picture danieljsinclair  ·  3Kommentare

BCup picture BCup  ·  3Kommentare

dogukankotan picture dogukankotan  ·  3Kommentare

benhathaway picture benhathaway  ·  3Kommentare

chitgoks picture chitgoks  ·  3Kommentare