時區
的Answer by Shiv V在正確的方向前進,但不是發現。答案忽略了time zone的關鍵問題。 Local…
類型故意丟失和忽略時區信息,這是他們的目的。但我們很少想要失去時區信息。
確定日期和時間取決於時區。對於任何特定時刻,全球的日期和時間可能會有所不同。在巴黎午夜過後的幾分鐘是新的一天,而在蒙特利爾仍然是「昨天」。
Instant
類定義了UTC時間軸上的一個時刻,分辨率爲nanoseconds。
Instant now = Instant.now();
如果期望的截止日期是「明天下午5點」,則必須指定時區作爲上下文。將ZoneId
應用於Instant
以獲得ZonedDateTime
。
ZoneId zoneId = ZoneId.of("America/Montreal");
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant , zoneId);
ZonedDateTime zdtTomorrow = zdt.plusDays(1);
現在調整爲下午5點。
LocalTime timeOfDayWhenDue = LocalTime.of(5 , 0);
ZonedDateTime zdtDeadline = zdtTomorrow.with(timeOfDayWhenDue);
您可以比較使用isEqual
,isBefore
和isAfter
方法。
ZonedDateTime now = ZonedDateTime.now(zoneId);
boolean overdue = now.isAfter(zdtDeadline);
您還可以將分區日期時間轉換回UTC。 ZonedDateTime
對象及其各自的Instant
對象在時間軸上(歷史上的同一時刻)代表相同的同時刻,但從不同時區(America/Montreal
與UTC
)的角度看。
Instant instantDeadline = zdtDeadline.toInstant();
Instant instantNow = now.toInstant();
boolean overdue = instantNow.isAfter(instantDeadline);
如果您想將最後期限傳達給印度的客戶,請調整到另一個時區。日期時間值將代表時間線上的同一時刻,但會顯示一個對該客戶有意義的wall-clock time。
ZoneId zoneId_Kolkata = ZoneId.of("Asia/Kolkata");
ZonedDateTime zdtDeadline_Kolkata = zdtDeadline.withZoneSameInstant(zoneId_Kolkata);
如果您不指定時區,則默認默認應用JVM的當前默認時區。不好。首先,隱含的假設使得你的代碼容易被誤解,並且使得錯誤更難以查明。更糟的是,默認情況下可以在任何時間更改,當您部署到另一臺計算機時,或者甚至在您的應用程序執行的任何時候在運行時!最好總是指定所需的/預期的時區。順便說一下,Locale
也是如此。
不要混合新的和舊的日期時間課程。新的是在Java 8及更高版本中構建的java.time包中。舊的不在java.time包中,應該避免(java.util.Date,java.util.Calendar,java.text.SimpleDateFormat)。舊班級獲得了一些新的方法來促進新舊數據類型之間的轉換。 –