日期時間 API 是 Java 8 發布的最重要功能之一。從一開始,Java 就缺乏一致的日期和時間處理方法,而 Java 8 日期時間 API 是核心 Java API 的一個受歡迎的新增功能。
我們為什麼需要新的 Java 日期時間 API?
在我們開始研究 Java 8 日期時間 API 之前,讓我們看看為什麼我們需要一個新的 API。現有的 java 日期和時間相關類存在幾個問題,其中一些是:
- Java 日期時間類沒有一致的定義,我們在 java.util 和 java.sql 包中都有 Date 類。同樣,格式化和解析類被定義在 java.text 包中。
- java.util.Date 同時包含日期和時間值,而 java.sql.Date 只包含日期值。將此放在 java.sql 包中是毫無意義的。而且,這兩個類具有相同的名稱,這本身就是一個非常糟糕的設計。
- 沒有明確定義的類用於時間、時間戳、格式化和解析。我們有 java.text.DateFormat 抽象類來滿足解析和格式化的需求。通常,會使用 SimpleDateFormat 類來進行解析和格式化。
- 所有的日期類都是可變的,因此它們不是線程安全的。這是 Java 日期和日曆類的最大問題之一。
- 日期類別並不提供國際化支援,也沒有時區支援。因此,java.util.Calendar 和 java.util.TimeZone 類別被引入,但它們也有上述列出的所有問題。
日期和日曆類別中定義的方法還有一些其他問題,但上述問題清楚地表明,Java 需要一個堅固的日期時間 API。這就是為什麼 Joda Time 作為 Java 日期時間需求的優質替代品發揮了關鍵作用。
Java 8 日期時間設計原則
Java 8 日期時間 API 是 JSR-310 的實現。它旨在克服遺留日期時間實現中的所有缺陷。新日期時間 API 的一些設計原則包括:
-
不可變性:新日期時間 API 中的所有類別都是不可變的,適用於多線程環境。
-
關注點分離:新 API 明確地區分了人類可讀的日期時間和機器時間(Unix 時間戳)。它為日期、時間、日期時間、時間戳、時區等定義了獨立的類別。
-
清晰度:方法清晰定義,並在所有類中執行相同的操作。例如,要獲取當前實例,我們有now()方法。所有這些類中都定義了format()和parse()方法,而不是為它們單獨創建一個類。
-
實用操作: 所有新的日期時間 API 類別都配備了執行常見任務的方法,例如加法、減法、格式化、解析、獲取日期/時間中的各個部分等。
-
可擴展: 新的日期時間 API 使用 ISO-8601 日曆系統,但我們也可以與其他非 ISO 日曆一起使用。
日期時間 API 套件
Java 8 日期時間 API 包括以下套件。
- java.time: 這是新的 Java 日期時間 API 的基本套件。所有主要的基本類都屬於此套件,如 LocalDate、LocalTime、LocalDateTime、Instant、Period、Duration 等。所有這些類都是不可變的且線程安全的。在大多數情況下,這些類將足以處理常見要求。
- java.time.chrono: 此套件定義了非 ISO 日曆系統的通用 API。我們可以擴展 AbstractChronology 類來創建自己的日曆系統。
- java.time.format:此套件包含用於格式化和解析日期時間物件的類別。大多數情況下,我們不會直接使用它們,因為java.time套件中的主要類別提供了格式化和解析方法。
- java.time.temporal:此套件包含時間物件,我們可以使用它來查找與日期/時間物件相關的特定日期或時間。例如,我們可以使用這些來查找月份的第一天或最後一天。您可以輕鬆識別這些方法,因為它們的格式總是“withXXX”。
- java.time.zone Package:此套件包含支援不同時區及其規則的類別。
Java 8 日期時間 API 類別示例
我們已經研究了Java日期時間API的大部分重要部分。現在是時候來看看日期時間API中最重要的類別及其示例了。
1. LocalDate
LocalDate是一個不可變的類別,代表具有默認格式yyyy-MM-dd的日期。我們可以使用now()方法來獲取當前日期。我們還可以為年、月和日提供輸入參數以創建LocalDate實例。
這個類提供了一個對 now() 方法的重載,我們可以傳遞 ZoneId 以獲取特定時區的日期。這個類提供了與 java.sql.Date 相同的功能。
在註釋中提供了 LocalDate 方法的解釋。當我們運行此程序時,我們會得到以下輸出。
2. LocalTime
LocalTime 是一個不可變的類,其實例代表了人類可讀格式的時間。它的默認格式是 hh:mm:ss.zzz。就像 LocalDate 一樣,這個類提供了時區支持,並且通過傳入小時、分鐘和秒作為輸入參數來創建實例。
輸出:
3. LocalDateTime
LocalDateTime是一個不可變的日期時間物件,表示具有默認格式yyyy-MM-dd-HH-mm-ss.zzz的日期時間。它提供了一個工廠方法,該方法接受LocalDate和LocalTime輸入參數以創建LocalDateTime實例。
在這三個示例中,我們看到如果為創建日期/時間提供無效參數,則會拋出java.time.DateTimeException,這是一個RuntimeException,因此我們不需要顯式地捕獲它。
我們也發現通過傳遞 ZoneId,可以獲得日期/時間數據,您可以從其 JavaDoc 獲得支持的 ZoneId 值列表。當我們運行上面的類時,我們獲得以下輸出。
4. Instant
Instant 類用於處理機器可讀的時間格式。Instant 將日期時間存儲在 Unix 時間戳中。
輸出:
Java 8 日期 API 實用程序
大多數日期時間原則類提供各種實用方法,如增加/減少天數、周數、月份等。還有一些其他實用方法用於使用 TemporalAdjuster 調整日期,以及計算兩個日期之間的時間段。
輸出:
Java 8日期解析和格式化
將日期格式化為不同格式,然後解析字符串以獲得日期時間對象是非常常見的。
輸出:
Java日期API遺留日期時間支持
遺留日期/時間類別幾乎在所有應用程式中使用,因此具有向後相容性是必不可少的。這就是為什麼有幾個實用工具方法,通過這些方法我們可以將遺留類別轉換為新類別,反之亦然。
輸出:
正如您所見,遺留的TimeZone
和GregorianCalendar
類別的toString()方法過於冗長,並且不夠用戶友好。
結論
I like this new Date Time API a lot. Some of the most used classes will be LocalDate and LocalDateTime. It’s very easy to work with the new classes. And, having similar methods that does a particular job makes it easy to find. It will take some time from moving legacy classes to new Date Time classes, but I believe it will be worth the time and effort.
Source:
https://www.digitalocean.com/community/tutorials/java-8-date-localdate-localdatetime-instant