檢查日期物件是否等於昨天
一、簡介
在 Java 應用程式中處理日期和時間資料時,出於各種目的(例如排程任務、提醒或報告)比較日期通常至關重要。常見的場景是需要確定給定日期相對於當前日期是否對應於昨天。在本教程中,我們將探索確定給定日期物件是否為昨天的各種方法。
2. 使用java.util.Calendar
常見的方法是使用java.util.Calendar
類別來操作日期和時間資訊。為了比較昨天的日期,我們透過 Calendar.getInstance() 實例化一個Calendar
物件Calendar.getInstance().
接下來,我們使用calendar.setTime(new Date())
將其時間設為目前日期,然後使用calendar.add(Calendar.DATE, -1)
減去一天。這產生了昨天的日期。
這是演示這些概念的程式碼片段:
Date date = new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24));
Calendar expectedCalendar = Calendar.getInstance();
expectedCalendar.setTime(date);
Calendar actualCalendar = Calendar.getInstance();
actualCalendar.add(Calendar.DATE, -1);
boolean isEqualToYesterday = expectedCalendar.get(Calendar.YEAR) == actualCalendar.get(Calendar.YEAR) &&
expectedCalendar.get(Calendar.MONTH) == actualCalendar.get(Calendar.MONTH) &&
expectedCalendar.get(Calendar.DAY_OF_MONTH) == actualCalendar.get(Calendar.DAY_OF_MONTH);
assertTrue(isEqualToYesterday);
由於兩個日期之間的毫秒數差異,使用此方法直接比較日期可能會失敗。這是因為Date
物件捕獲日期和時間,包括毫秒。如果時間分量不完全相同,則比較可能會產生不正確的結果。
為了緩解此問題,一種方法是在執行比較之前截斷兩個日期的時間部分。我們使用各自的get(Calendar.YEAR)
、 get(Calendar.MONTH)
和get(Calendar.DAY_OF_MONTH)
方法從兩個日期中提取年、月和日部分,以單獨確定actualCalendar
是否等於昨天。
儘管這些類別被視為遺留 API,但它們仍然被廣泛使用,特別是在較新的 Java 版本不可用的環境中。
3.使用java.util.Date
毫秒
此方法利用了Date
物件內部儲存自紀元(1970 年 1 月 1 日,00:00:00 UTC)以來的毫秒數這一事實。它涉及以毫秒為單位計算昨天的午夜,並將其與Date
物件的getTime()
值進行比較。
我們使用Instant.now().minus(1, ChronoUnit.DAYS).toEpochMilli()
以毫秒計算昨天的午夜。此操作從當前時刻減去一天,並將其轉換為自紀元以來的毫秒數,有效地表示前一天午夜的時間戳記。
隨後,我們將此計算值與給定的expectedDate
的getTime()
值進行比較。透過驗證expectedDate
是否落在從昨天午夜時間戳到下一個午夜( yesterdayMidnightMillis
+ 86_400_000 毫秒)的範圍內,我們可以確定yesterdayMidnightMillis
是否對應於昨天的日期。
讓我們用一個簡單的例子來示範這個方法:
Date expectedDate = new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24));
long yesterdayMidnightMillis = Instant.now()
.minus(1, ChronoUnit.DAYS)
.toEpochMilli();
boolean isEqualToYesterday = expectedDate.getTime() >= yesterdayMidnightMillis && expectedDate.getTime() < yesterdayMidnightMillis + 86_400_000;
assertTrue(isEqualToYesterday);
這種方法提供了一種簡單而有效的方法來使用毫秒來比較日期。它適用於需要與舊版Date
物件直接比較的場景。
4.使用java.time.LocalDate
處理日期運算的另一種方法是使用LocalDate
類別及其minusDays()
方法。這種方法是 Java 8 中引入的現代日期和時間 API 的一部分。
LocalDate
提供了一種更直接、更直觀的日期處理方式。它旨在僅專注於年、月和日組件,而不包含時間組件。這使得它非常適合僅日期操作,例如記錄歷史日期或報告日期過濾。
要使用此方法比較昨天的日期,我們首先使用LocalDate.now()
來取得當前日期。然後,我們只需呼叫LocalDate
物件的minusDays(1)
方法來減去一天,得到昨天的日期:
Date date = new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24));
LocalDate expectedLocalDate = LocalDate.of(date.getYear() + 1900, date.getMonth() + 1, date.getDate());
LocalDate actualLocalDate = LocalDate.now().minusDays(1);
boolean isEqualToYesterday = expectedLocalDate.equals(actualLocalDate);
assertTrue(isEqualToYesterday);
在此範例中,我們透過從Date
物件中提取年、月和日部分來指定昨天的日期。但請注意, getYear()
方法傳回自 1900 年以來的年份,而getMonth()
傳回從 0 開始的月份索引。因此,我們將 1900 新增到getYear()
並將 1 加到getMonth()
以將它們調整為標準日期表示形式。
建議 Java 版本 8 及更高版本使用LocalDate
進行日期操作。
5. 使用 Joda-Time
Joda-Time 是一個流行的 Java 日期和時間庫。我們可以使用這個函式庫來檢查日期物件是否代表昨天的日期。為了使用 Joda-Time 比較昨天的日期,我們利用DateTime
類別及其minusDays()
方法。
首先,我們使用DateTime.now()
來取得目前日期和時間。然後,我們透過呼叫minusDays(1)
方法從目前日期減去一天,得到昨天的日期:
Date date = new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24));
DateTime expectedDateTime = new DateTime(date).withTimeAtStartOfDay();
DateTime actualDateTime = DateTime.now().minusDays(1).withTimeAtStartOfDay();
boolean isEqualToYesterday = expectedDateTime.equals(actualDateTime);
assertTrue(isEqualToYesterday);
與Calendar
類別類似,Joda-Time 的DateTime
類別捕捉時間和日期,因此,直接比較它們可能會因毫秒差異而導致不準確。
為了解決這個問題,我們可以利用 Joda-Time 提供的withTimeAtStartOfDay()
方法,而不是將日期值分解為年、月和日。此方法將DateTime
物件的時間部分設定為一天的開始,從而有效地將時間重設為午夜 (00:00:00)。透過將withTimeAtStartOfDay()
應用於DateTime
對象,我們確保只有日期部分對於比較目的仍然重要。
六,結論
在本文中,我們探討了幾種確定日期物件是否屬於昨天日期的方法。對於大多數使用 Java 8 或更高版本的現代 Java 應用程序,通常建議使用LocalDate
方法,因為它的清晰度、不可變性以及對各種日期操作的支援。
雖然 Joda-Time 是一個成熟且穩定的函式庫,但隨著越來越多的專案過渡到標準 Java 日期和時間 API,其未來的開發和支援可能會變得不太確定。
與往常一樣,範例的原始程式碼可在 GitHub 上取得。