Java 8 date-Heure: début de la journée à partir de ZonedDateTime

quelle Est la différence entre ces:

zonedDateTime.truncatedTo(ChronoUnit.DAYS);

zonedDateTime.toLocalDate().atStartOfDay(zonedDateTime.getZone());

Aucune raison de préférer l'une contre l'autre?

Merci

39
demandé sur JodaStephen 2015-03-19 14:55:12

3 réponses

mise à jour par souci de correction:

Dans la plupart des cas, oui le même, voir l'exemple suivant pour le Brésil lors du passage de l'hiver à l'heure d'été:

ZonedDateTime zdt = 
  ZonedDateTime.of(2015, 10, 18, 0, 30, 0, 0, 
    ZoneId.of("America/Sao_Paulo")); // switch to summer time
ZonedDateTime zdt1 = zdt.truncatedTo(ChronoUnit.DAYS);
ZonedDateTime zdt2 = zdt.toLocalDate().atStartOfDay(zdt.getZone());

System.out.println(zdt); // 2015-10-18T01:30-02:00[America/Sao_Paulo]
System.out.println(zdt1); // 2015-10-18T01:00-02:00[America/Sao_Paulo]
System.out.println(zdt2); // 2015-10-18T01:00-02:00[America/Sao_Paulo]

la troncature se produit sur la ligne de temps locale. Si vous choisissez des jours, vous optez pour minuit. Selon javadoctruncate()-méthode enfin convertit à la nouvelle ZonedDateTime et déplace le temps vers l'avant en fonction de la taille de l'intervalle (1 heure).

conversion de la zdt premier LocalDate (en coupant la partie du temps) et ensuite à la recherche de sa ZonedDateTimedans le fuseau horaire est effectivement la même chose pour cette situation.

toutefois, dans le cas inverse du passage de l'heure d'été à l'heure d'hiver, il y a une exception près (merci beaucoup à @Austin qui a donné un contre-exemple). Le problème est de savoir à quel moment choisir le décalage à utiliser pendant le chevauchement. Habituellement la classe ZonedDateTime est conçu et spécifié d'utiliser le décalage, voir aussi cet extrait de l' Javadoc:

pour les chevauchements, la stratégie générale est que si la date-heure locale tombe au milieu d'un Chevauchement, le décalage sera conserver. S'il n'y a pas de décalage précédent, ou si le décalage précédent est invalide, alors le décalage plus tôt est utilisé, typiquement l'heure "d'été".

Si la classe ZonedDateTime suivrait donc ses propres spécifications, alors les deux procédures seraient encore signification équivalente:

zdt.truncatedTo(ChronoUnit.DAYS);

devrait être équivalent à

zdt.toLocalDate().atStartOfDay().atZone(zdt.getZone()).withEarlierOffsetAtOverlap();

Mais le comportement réel, selon l'exemple de @Austin et confirmé par mes propres tests est:

zdt.toLocalDate().atStartOfDay().atZone(zdt.getZone()).withLaterOffsetAtOverlap();

ressemble à une incohérence cachée dans la classe ZonedDateTime, légèrement parlé. Si vous me demandez quelle méthode préférer alors je préférerais préconiser la seconde méthode bien qu'elle soit beaucoup plus longue et nécessite plus de frappes. Mais il a le gros avantage d'être plus transparent sur ce qu'il fait. Une autre raison de préférer la deuxième approche est:

il obtient vraiment le premier instant où l'heure locale est égale au début de la journée. Sinon, en utilisant la première méthode, vous devez écrire:

zdt.truncatedTo(ChronoUnit.DAYS).withEarlierOffsetAtOverlap();
36
répondu Meno Hochschild 2017-01-13 12:56:08

ils sont légèrement différents. Selon la documentation javadoc, truncatedTo() va essayer de préserver le fuseau horaire dans le cas de chevauchement, mais atStartOfDay() va trouver la première occurrence de minuit.

par exemple, Cuba rétablit l'heure d'été à 1 h du matin et retombe à 12 h. Si vous commencez avec un temps après la transition, atStartOfDay() retournera la première occurrence de 12h, alors que truncatedTo() retour de la seconde occurence.

ZonedDateTime zdt = ZonedDateTime.of(2016, 11, 6, 2, 0, 0, 0, ZoneId.of("America/Havana"));
ZonedDateTime zdt1 = zdt.truncatedTo(ChronoUnit.DAYS);
ZonedDateTime zdt2 = zdt.toLocalDate().atStartOfDay(zdt.getZone());

System.out.println(zdt);  // 2016-11-06T02:00-05:00[America/Havana]
System.out.println(zdt1); // 2016-11-06T00:00-05:00[America/Havana]
System.out.println(zdt2); // 2016-11-06T00:00-04:00[America/Havana]
25
répondu Austin 2017-01-13 00:49:12

Remarque: il y a aussi une autre façon de le faire:

zonedDateTime.with(LocalTime.MIN);

qui produit le même résultat que truncatedTo

5
répondu nevster 2017-10-23 05:38:52