Moment: endOf('day') échoue les jours qui ne commencent pas à minuit

Créé le 20 avr. 2016  ·  15Commentaires  ·  Source: moment/moment

Considérer:

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

Dans la plupart des fuseaux horaires, cela renverra "2016-10-16 23:59:59" . Cependant, au Brésil, cela renverra "2016-10-17 00:59:59" . Ceci est incorrect, car seule l'heure de 00:00 à 00:59 le 2016-10-16 est manquante. La fin du 2016-10-16 est toujours 23:59:59 à la même date.

Ceci est également reproductible avec moment-fuseau horaire :

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

Le problème est dans la méthode endOf . Pour calculer la fin de la journée, nous prenons le _début_ de la journée, ajoutons un jour, puis soustrayons une milliseconde. Cette logique est erronée lorsque la journée ne commence pas à minuit. Au lieu d'ajouter un jour, nous devons ajouter la durée exacte de la journée en question.

Bug DST

Tous les 15 commentaires

Cela a été initialement signalé comme moment/moment-timezone#327.

2749 est lié, mais légèrement différent.

Au lieu de calculer la durée exacte de la journée, ne pouvez-vous pas simplement faire :

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

Fonctionne très bien le 15 lorsqu'il est poussé dans le 16 également :

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

Y a-t-il un cas limite auquel je ne pense pas ?

Je suppose qu'il pourrait y avoir un avantage en termes de performances à le faire différemment, mais bon sang, vous pouvez le lire !

Hmmmm, autre chose de fou ici :

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"

Ne traitons-nous que du comportement ambigu du navigateur ici ? Ou y a-t-il quelque chose de plus?

En chrome avec le fuseau horaire windows de 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"

En chrome avec mon fuseau horaire en utilisant 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"

FRAIS!

Quelque chose avec le fuseau horaire du moment ? Je ne connais pas vraiment ce code donc c'est difficile à dire. Cela ne ressemble pas au navigateur si le premier fonctionne cependant.

Je pense que cela est dû au fait que le fuseau horaire du moment repoussera toujours une date invalide, si elle a été "ajoutée" à cette date. Que ce soit par conception ou par accident, je ne suis pas sûr.

//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"

Je pense que cela a quelque chose à voir avec le fait d'essayer d'utiliser le paramètre keepTime lorsque vous ne pouvez pas garder l'heure. Je ne connais pas assez bien ce code pour vous dire pourquoi le code est tel qu'il est, mais je sais avec certitude que si l'appel keepTime dans ce code était 0 au lieu de 1, tout se déroulerait comme prévu. C'est parce que le chronomètre est activé qu'il est repoussé. Et gardez le temps devrait être activé, c'est juste génial avec cet étui de bord.

    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);
            }
        }
    };

Je ne connais pas assez le fuseau horaire pour être utile ici, mais peut-être que le ticket expliquant pourquoi keepTime est utilisé sera utile à quiconque enquête : https://github.com/moment/moment-timezone/ numéros/28

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

C'est le dernier grand changement dans les zones de manipulation pour le moment. Je ne sais pas si c'est lié à ce problème, mais cela devrait aider.

@maggiepint pouvez-vous expliquer un peu le

repoussera toujours une date invalide

partie. Je veux dire -- avons-nous un exemple qui expose un problème avec moment-timezone, ou avons-nous juste besoin d'un code intelligent en moment pour détecter l'heure d'été au début/à la fin de la journée et le gérer de manière appropriée. La seconde est moyenne à facile. Si nous devons refactoriser à nouveau la zone passant entre le moment-tz et le moment, alors c'est l'enfer - je préfère attendre 3.0 et espérer que la nouvelle interface n'aura pas ce problème.

@ichernev dans l'état actuel du code, nous avons deux problèmes dans ce problème. L'un est le problème soulevé à l' origine par

L'autre est que le fuseau horaire du moment, lorsqu'il est présenté avec une date invalide, avance si cette date invalide est utilisée dans le constructeur, mais il recule s'il est « ajouté » à cette date. C'est, en l'état, un problème avec le fuseau horaire du moment et non le moment. Je ne sais pas comment l'interface du fuseau horaire change cela - je devrais y réfléchir un peu.

@maggiepint merci pour l'explication claire.

Donc pour régler le problème du moment : endOf('day') étant inexact -- juste "viser" pour la fin de la journée, allez-y, s'il est 00:00, terminez, sinon visez à nouveau, si le deuxième objectif atteint 00 : 00 nous avons terminé sinon utilisez le premier coup. Le deuxième objectif sera utile si nous sautons à travers l'heure d'été et sommes "déformés" d'une heure. Si la fin de la journée est une heure invalide à cause de l'heure d'été, le deuxième objectif ne fera pas de mal.

Nous devrions utiliser cet algorithme pour tous les endOf , peut-être même startOf , mais c'est plus difficile à raisonner avec la mise à zéro que nous faisons actuellement.

Salut les gars, je suis également affecté par ce problème sur la version actuelle de moment (2.14.1).

J'ai envoyé #3716 pour résoudre ce problème, mais je rencontre actuellement des problèmes avec Travis CI pour des raisons de transpile. Je l'examinerai plus prochainement.

Celui-ci est également lié (locale brésilienne par défaut).

Résultats de l'opération à la même date :

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

Hé - Je viens de soumettre #4164 qui corrige cela pour startOf ainsi que endOf. J'adorerais avoir des commentaires là-bas afin que nous puissions, espérons-le, enfin faire avancer les choses.

@ mj1856 , j'ai fermé mon PR car le problème avec endOf dans le bord DST semble être résolu. Cela pourrait-il être corrigé aussi?

J'ai testé le #4164 et cela semble être corrigé. En attente de fusion.

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