上一篇文章『Java 的時間日期 API』中,咱們學習了由 Date、Calendar,DateFormat 等組成的「傳統時間日期 API」,可是傳統的處理接口設計並非很友好,不易使用。終於,Java 8 借鑑第三方優秀開源庫 Joda-time,從新設計了一套 API。java
那麼本篇文章就來簡單學習一下新式的時間日期處理接口。git
Instant 和 Date 同樣,表示一個時間戳,用於描述一個時刻,只不過它較 Date 而言,能夠描述更加精確的時刻。而且 Instant 是時區無關的。github
Date 最多能夠表示毫秒級別的時刻,而 Instant 能夠表示納秒級別的時刻。例如:安全
看看代碼:bash
public static void main(String[] args){
//建立 Instant 實例
Instant instant = Instant.now();
System.out.println(instant);
Instant instant1 = Instant.ofEpochSecond(20);
System.out.println(instant1);
Instant instant2 = Instant.ofEpochSecond(30,100);
System.out.println(instant2);
Instant instant3 = Instant.ofEpochMilli(1000);
System.out.println(instant3);
}
複製代碼
輸出結果:微信
2018-04-23T02:43:10.973Z
1970-01-01T00:00:20Z
1970-01-01T00:00:30.000000100Z
1970-01-01T00:00:01Z
複製代碼
能夠看到,Instant 和 Date 不一樣的是,它是時區無關的,始終是格林零時區相關的,也便是輸出的結果始終格林零時區時間。markdown
不一樣於 Calendar 既能處理日期又能處理時間,java.time 的新式 API 分離開日期和時間,用單獨的類進行處理。LocalDate 專一於處理日期相關信息。工具
LocalDate 依然是一個不可變類,它關注時間中年月日部分,咱們能夠經過如下的方法構建和初始化一個 LocalDate 實例:學習
看看代碼:spa
public static void main(String[] args){ //構建 LocalDate 實例 LocalDate localDate = LocalDate.now(); System.out.println(localDate); LocalDate localDate1 = LocalDate.of(2017,7,22); System.out.println(localDate1); LocalDate localDate2 = LocalDate.ofYearDay(2018,100); System.out.println(localDate2); LocalDate localDate3 = LocalDate.ofEpochDay(10); System.out.println(localDate3); } 複製代碼
輸出結果:
2018-04-23
2017-07-22
2018-04-10
1970-01-11
複製代碼
須要注意一點,LocalDate 會根據系統中當前時刻和默認時區計算出年月日的信息。
除此以外,LocalDate 中還有大量關於日期的經常使用方法:
這些方法都見名知意,此處再也不贅述。
相似於 LocalDate,LocalTime 專一於時間的處理,它提供小時,分鐘,秒,毫微秒的各類處理,咱們依然能夠經過相似的方式建立一個 LocalTime 實例。
一樣的,LocalTime 默認使用系統默認時區處理時間,看代碼:
public static void main(String[] a){ LocalTime localTime = LocalTime.now(); System.out.println(localTime); LocalTime localTime1 = LocalTime.of(23,59); System.out.println(localTime1); LocalTime localTime2 = LocalTime.ofSecondOfDay(10); System.out.println(localTime2); } 複製代碼
輸出結果:
13:59:03.723
23:59
00:00:10
複製代碼
固然,LocalTime 中也一樣封裝了不少好用的工具方法,例如:
LocalDateTime 類則是集成了 LocalDate 和 LocalTime,它既能表示日期,又能表述時間信息,方法都相似,只是有一部分涉及時區的轉換內容,咱們待會說。
不管是咱們的 LocalDate,或是 LocalTime,甚至是 LocalDateTime,它們基本是時區無關的,內部並無存儲時區屬性,而基本用的系統默認時區。每每有些場景之下,缺少必定的靈活性。
ZonedDateTime 能夠被理解爲 LocalDateTime 的外層封裝,它的內部存儲了一個 LocalDateTime 的實例,專門用於普通的日期時間處理。此外,它還定義了 ZoneId 和 ZoneOffset 來描述時區的概念。
ZonedDateTime 和 LocalDateTime 的一個很大的不一樣點在於,後者內部並無存儲時區,因此對於系統的依賴性很強,每每換一個時區可能就會致使程序中的日期時間不一致。
然後者則能夠經過傳入時區的名稱,使用 ZoneId 進行匹配存儲,也能夠經過傳入與零時區的偏移量,使用 ZoneOffset 存儲時區信息。
因此,構建一個 ZonedDateTime 實例有如下幾種方式:
看代碼:
public static void main(String[] a){ ZonedDateTime zonedDateTime = ZonedDateTime.now(); System.out.println(zonedDateTime); LocalDateTime localDateTime = LocalDateTime.now(); ZoneId zoneId = ZoneId.of("America/Los_Angeles"); ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime,zoneId); System.out.println(zonedDateTime1); Instant instant = Instant.now(); ZoneId zoneId1 = ZoneId.of("GMT"); ZonedDateTime zonedDateTime2 = ZonedDateTime.ofInstant(instant,zoneId1); System.out.println(zonedDateTime2); } 複製代碼
輸出結果:
2018-04-23T16:10:29.510+08:00[Asia/Shanghai]
2018-04-23T16:10:29.511-07:00[America/Los_Angeles]
2018-04-23T08:10:29.532Z[GMT]
複製代碼
簡單解釋一下,首先第一個輸出應該沒什麼問題,系統保存當前系統日期和時間以及默認的時區。
第二個小例子,LocalDateTime 實例保存了時區無關的當前日期時間信息,也就是這裏的年月日時分秒,接着構建一個 ZonedDateTime 實例並傳入一個美國時區(西七區)。你會發現輸出的日期時間爲西七區的 16 點 29 分。
像這種關聯了時區的日期時間就很可以解決那種,換時區致使程序中時間錯亂的問題。由於我關聯了時區,不管你程序換到什麼地方運行了,日期+時區 本就已經惟一肯定了某個時刻,就至關於我在存儲某個時刻的時候,我說明了這是某某時區的某某時間,即使你換了一個地區,你也不至於把這個時間按本身當前的時區進行解析並直接使用了吧。
第三個小例子就更加的直接明瞭了,構建 ZonedDateTime 實例的時候,給定一個時刻和一個時區,而這個時刻值就是相對於給定時區的標準時間所通過的毫秒數。
有關 ZonedDateTime 的其餘日期時間的處理方法和 LocalDateTime 是同樣的,由於 ZonedDateTime 是直接封裝了一個 LocalDateTime 實例對象,因此全部相關日期時間的操做都會間接的調用 LocalDateTime 實例的方法,咱們再也不贅述。
Java 8 的新式日期時間 API 中,DateTimeFormatter 做爲格式化日期時間的主要類,它與以前的 DateFormat 類最大的不一樣就在於它是線程安全的,其餘的使用上的操做基本相似。咱們看看:
public static void main(String[] a){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(formatter.format(localDateTime)); String str = "2008年08月23日 23:59:59"; DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"); LocalDateTime localDateTime2 = LocalDateTime.parse(str,formatter2); System.out.println(localDateTime2); } 複製代碼
輸出結果:
2018年04月23日 17:27:24
2008-08-23T23:59:59
複製代碼
格式化主要有兩種狀況,一種是將日期時間格式化成字符串,另外一種則是將格式化的字符串裝換成日期時間對象。
DateTimeFormatter 提供將 format 方法將一個日期時間對象轉換成格式化的字符串,可是反過來的操做卻建議使用具體的日期時間類本身的 parse 方法,這樣能夠省去類型轉換的步驟。
現實項目中,咱們也常常會遇到計算兩個時間點之間的差值的狀況,最粗暴的辦法是,所有幻化成毫秒數並進行減法運算,最後在轉換回日期時間對象。
可是 java.time 包中提供了兩個日期時間之間的差值的計算方法,咱們一塊兒看看。
關於時間差的計算,主要涉及到兩個類:
例如:
public static void main(String[] args){ LocalDate date = LocalDate.of(2017,7,22); LocalDate date1 = LocalDate.now(); Period period = Period.between(date,date1); System.out.println(period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "天"); LocalTime time = LocalTime.of(20,30); LocalTime time1 = LocalTime.of(23,59); Duration duration = Duration.between(time,time1); System.out.println(duration.toMinutes() + "分鐘"); } 複製代碼
輸出結果:
0年9月1天
209分鐘
複製代碼
顯然,年月日的日期間差值的計算使用 Period 類足以,而時分秒毫秒的時間的差值計算則須要使用 Duration 類。
最後,關於 java.time 包下的新式日期時間 API,咱們簡單的學習了下,並無深刻到源碼實現層次進行介紹,由於底層涉及大量的系統接口,涉及到大量的抽象類和實現類,有興趣的朋友能夠自行閱讀 jdk 的源碼深刻學習。
文章中的全部代碼、圖片、文件都雲存儲在個人 GitHub 上:
(https://github.com/SingleYam/overview_java)
歡迎關注微信公衆號:撲在代碼上的高爾基,全部文章都將同步在公衆號上。