得到一天的開始有這些有什麼區別:的Java 8日期時間:從ZonedDateTime
zonedDateTime.truncatedTo(ChronoUnit.DAYS);
zonedDateTime.toLocalDate().atStartOfDay(zonedDateTime.getZone());
任何理由,更喜歡一個對其他?
感謝
得到一天的開始有這些有什麼區別:的Java 8日期時間:從ZonedDateTime
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,那麼你選擇午夜。根據javadoctruncate()
- 方法最終轉換回新的ZonedDateTime
並將時間向前移動差距的大小(1小時)。
首先將zdt轉換爲LocalDate
(切斷時間部分),然後在給定時區中查找其ZonedDateTime
-部分對於這種情況實際上是相同的。
但是,對於從夏令時切換回冬令時的情況,有一個例外(非常感謝@奧斯汀誰反例)。問題出在重疊時決定使用哪個偏移量。通常情況下,類ZonedDateTime
設計/指定使用以前的偏移,也看到Javadoc此摘錄:
對於重疊,一般的策略是,如果本地日期,時間 落在重疊的中間,那麼之前的偏移量將保留爲 。如果沒有先前的偏移量,或者先前的偏移量爲 無效,則使用較早的偏移量,通常爲「夏季」時間。
如果該類ZonedDateTime
將因此走自己的規範,然後這兩個過程將仍然是等價的含義:
zdt.truncatedTo(ChronoUnit.DAYS);
應相當於
zdt.toLocalDate().atStartOfDay().atZone(zdt.getZone()).withEarlierOffsetAtOverlap();
但根據實際行爲@Austin的例子,並在我自己的測試中確認是:
zdt.toLocalDate().atStartOfDay().atZone(zdt.getZone()).withLaterOffsetAtOverlap();
看起來像是在類ZonedDateTime
中隱含的不一致,說話溫和。如果你問我哪種方法是首選,那麼我寧願提倡第二種方法,儘管它要長得多,而且需要更多擊鍵。但它對於它的功能更加透明有很大的好處。偏好第二種方法的另一個原因是:
它確實獲得了當地時間等於一天的第一個時刻。否則,在使用第一種方法時,您必須編寫:
zdt.truncatedTo(ChronoUnit.DAYS).withEarlierOffsetAtOverlap();
這並不總是正確的!看到我的答案爲什麼不。 – Austin 2017-01-13 00:54:15
@奧斯汀你的答案似乎是合理的。我會相應地調查並糾正我的答案。 – 2017-01-13 07:46:28
它們略有不同。根據javadocs,truncatedTo()
將嘗試在重疊的情況下保留時區,但atStartOfDay()
將查找午夜的首次出現。
例如,古巴恢復夏令時凌晨1點,回落到上午12點。如果您從該轉換後的某個時間開始,則atStartOfDay()
將返回上午12點的第一次出現,而truncatedTo()
將返回第二次出現。
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]
非常感謝您找到了反例。提高了你的意見並更新了我的答案。 – 2017-01-13 10:48:29
注意,也這樣做的另一種方式:
zonedDateTime.with(LocalTime.MIN);
產生相同的結果truncatedTo
這不是一個真正的答案。 – shmosel 2017-10-23 05:41:32
難道他們不能只是把方法'atStartOfDay()'的'ZonedDataTime'類? – Przemek 2016-01-14 08:12:46