1. ホーム
  2. java

Java 8 の日付時間:ZonedDateTime から日の始まりを取得する

2023-08-31 02:25:55

質問

これらは何か違いがあるのでしょうか。

zonedDateTime.truncatedTo(ChronoUnit.DAYS);

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

どちらか一方を選ぶ理由は?

ありがとうございます。

どのように解決するのですか?

訂正のため、更新しました。

ほとんどの場合、同じです。 ブラジルで冬時間から夏時間への切り替えを行った場合の例をご覧ください。

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]

切り捨てはローカルタイムライン上で行われます。DAYSを選択した場合は、真夜中を選択することになります。によると javadoc truncate() -メソッドに変換され、最終的に新しい ZonedDateTime に変換し、時間をずらした分(1時間)前に戻します。

最初にzdtを変換して LocalDate に変換し (時間の部分をカットして)、その ZonedDateTime -を探すのと、与えられたタイムゾーンの部分を探すのは、この状況では事実上同じことです。

しかし、夏時間から冬時間に戻るという逆のケースには 一つの例外 があります (反対の例を出してくれた @Austin にとても感謝します)。問題は、どのオフセットを使用するかを決定するオーバーラップ時です。通常、クラス ZonedDateTime は前のオフセットを使用するように設計/指定されています。 Javadoc :

オーバーラップについて、一般的な戦略は、ローカルの日付時刻がオーバーラップの中間に位置する場合 がオーバーラップの中央に位置する場合、以前のオフセットが保持されます。 保持されます。前のオフセットがない場合、または前のオフセットが無効な場合は、以前のオフセットが使用されます。 前のオフセットがない場合、または前のオフセットが無効な場合は、以前のオフセットが使用され、通常は "summer"時間です。

もしクラス ZonedDateTime が結果的にそれ自身の仕様に従うのであれば、両方の手続きはまだ同等の意味となるでしょう。

zdt.truncatedTo(ChronoUnit.DAYS);

と同等でなければなりません。

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

しかし、@Austin の例によると、実際の動作は、私自身のテストでも確認されています。

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

クラスに隠れた矛盾があるように見える ZonedDateTime と穏やかに話しています。どの方法がいいかと聞かれたら、私はむしろ2番目の方法を支持します。しかし、この方法には、何をするのかがより明確になるという大きな利点があります。2番目の方法を好むもう1つの理由は、次のとおりです。

ローカルタイムが一日の始まりと等しくなる最初の瞬間を本当に取得することです。そうでなければ、最初の方法を使用するとき、あなたは書かなければなりません。

zdt.truncatedTo(ChronoUnit.DAYS).withEarlierOffsetAtOverlap();