1. 程式人生 > >Java8新的時間日期庫及使用示例(LocalDate LocalTime )

Java8新的時間日期庫及使用示例(LocalDate LocalTime )

java8引入了一套全新的時間日期API,本篇隨筆將說明學習java8的這套API。

java。time包中的是類是不可變且執行緒安全的。新的時間及日期API位於java.time中,下面是一些關鍵類

●Instant——它代表的是時間戳

●LocalDate——不包含具體時間的日期,比如2014-01-14。它可以用來儲存生日,週年紀念日,入職日期等。

●LocalTime——它代表的是不含日期的時間

●LocalDateTime——它包含了日期及時間,不過還是沒有偏移資訊或者說時區。

●ZonedDateTime——這是一個包含時區的完整的日期時間,偏移量是以UTC/格林威治時間為基準的。

java8是如何處理時間及日期的

1、如何在java8中獲取當天的日期

java8中有個叫LocalDate的類,能用來表示今天的日期。這個類與java.util.Date略有不同,因為它只包含日期,沒有時間。

可以看到,他建立了今天的日期卻不包含時間資訊,並且格式化了日期。

 

 

2、如何在java8中獲取當前的年月日

LocalDate類中提供了一些很方便的方法可以用來提取年月日以及其他的日期屬性,特別方便,只需要使用對應的getter方法就可以了,非常直觀

 

3、在java8中如何獲取某個特定的日期

通過另一個方法,可以創建出任意一個日期,它接受年月日的引數,然後返回一個等價的LocalDate例項。在這個方法裡,需要的日期你填寫什麼就是什麼,不想之前的API中月份必須從0開始

 

4、在java8中檢查兩個日期是否相等

LocalDate重寫了equals方法來進行日期的比較,如下所示:

 

 

5、在java8中如何檢查重複事件,比如生日

在java中還有一個與時間日期相關的任務就是檢查重複事件,比如每月的賬單日

如何在java中判斷是否是某個節日或者重複事件,使用MonthDay類。這個類由月日組合,不包含年資訊,可以用來代表每年重複出現的一些日期或其他組合。他和新的日期庫中的其他類一樣也都是不可變且執行緒安全的,並且它還是一個值類(value class)。

通過列子可以看到MonthDay只儲存了月日,對比兩個日期的月日即可知道是否重複

 

6、如何在java8中獲取當前時間

這個與第一個例子獲取當前日期非常相似,這裡用的是LocalTime類,預設的格式是hh:mm:ss:nnn

可以看到,這個時間是不包含日期的

 

7、如何增加時間裡面的小時數

很多時候需要對時間進行操作,比如加一個小時來計算之後的時間,java8提供了更方便的方法 如plusHours,這些方法返回的是一個新的LocalTime例項的引用,因為LocalTime是不可變的

 

8、如何獲取1周後的日期

這個與前一個獲取2小時後的時間的例子很相似,這裡我們獲取的是1周後的日期。LocalDate是用來表示無時間的日期,他又一個plus()方法可以用來增加日,星期,月,ChronoUnit則用來表示時間單位,LocalDate也是不可變的,因此任何修改操作都會返回一個新的例項

可以看到一週後的日期是什麼,也可以用這個方法來增加一個月,一年,一小時,一分等等

 

9、一年前後的日期

 在上個例子中我們使用了LocalDate的plus()方法來給日期增加日周月,現在我們用minus()方法來找出一年前的那天

 

10、在java8中使用時鐘

java8自帶了Clock類,可以用來獲取某個時區下(所以對時區是敏感的)當前的瞬時時間、日期。用來代替System.currentTimelnMillis()與TimeZone.getDefault()方法

 

11、在java中如何判斷某個日期在另一個日期的前面還是後面

 如何判斷某個日期在另一個日期的前面還是後面或者相等,在java8中,LocalDate類中使用isBefore()、isAfter()、equals()方法來比較兩個日期。如果呼叫方法的那個日期比給定的日期要早的話,isBefore()方法會返回true。equals()方法在前面的例子中已經說明了,這裡就不舉例了

可以看到java8中比較日期非常簡單,不再需要使用Calendar這樣另外的類來完成類似的任務了

 

12、在java8中處理不同的時區

java8中不僅將日期和時間進行了分離,同時還有時區。比如ZonId代表的是某個特定時區,ZonedDateTime代表帶時區的時間,等同於以前的GregorianCalendar類。使用該類,可以將本地時間轉換成另一個時區中的對應時間。

注意:對應時區的文字可以直接手動填寫,也可以呼叫定義好了的,手動填寫的時候注意不可填錯了,否則你會遇到下面的異常

13、如何表示固定的日期,比如信用卡過期時間

正如MonthDay表示的是某個重複出現的日子,YearMonth是另外一個組合,代表的是像信用卡還款日,定期存款到期日,options到期日這類的日期。你可以用這個類找出這個月有多少天,LengthOfMonth()這個方法返回的是這個YearMonth例項有多少天,這對於檢查2月是否潤2月很有用

14、如何在java8中檢查閏年

LocalDate類由一個isLeapYear()方法來返回當前LocalDate對應的那年是否是閏年

 

15、兩個日期之間包含多少天,多少月

計算兩個日期之間包含多少天、周、月、年。可以用java.time.Period類完成該功能。下面例子中將計算日期與將來的日期之間一共有幾個月

 

16、帶時區的日期與時間

在java8中,可以使用ZoneOffset來代表某個時區,可以使用它的靜態方法ZoneOffset.of()方法來獲取對應的時區,只要獲得了這個偏移量,就可以用這個偏移量和LocalDateTime建立一個新的OffsetDateTime

可以看到現在時間日期和時區關聯上了,注意OffsetDateTime主要是用來給機器理解的,平時使用就用前面結束的ZoneDateTime類就可以了

 

17、在java8中獲取當前時間戳

java8獲取時間戳特別簡單。Instant類由一個靜態的工廠方法now()可以返回當前時間戳

可以看到,當前時間戳是包含日期和時間的,與java.util.Date很類似,事實上Instant就是java8以前的Date,可以使用這個兩個類中的方法在這兩個型別之間進行轉換,比如Date.from(Instant)就是用來把Instant轉換成java.util.date的,而Date。toInstant()就是將Date轉換成Instant的

 

18,如何在java8中使用預定義的格式器來對日期進行解析/格式化

在java8之前,時間日期的格式化非常麻煩,經常使用SimpleDateFormat來進行格式化,但是SimpleDateFormat並不是執行緒安全的。在java8中,引入了一個全新的執行緒安全的日期與時間格式器。並且預定義好了格式。比如,本例中使用的BASICISODATE格式會將20160414格式化成2016-04-14

在DateTimeFormatter中還有很多定義好的格式,有興趣的可以自己去看一下

 

19、如何在java中使用自定義的格式器來解析日期

 在上例中,我們使用了預置的時間日期格式器來解析日期字串了,但是有時預置的不能滿足的時候就需要我們自定義日期格式器了,下面的例子中的日期格式是"MM dd yyyy".你可以給DateTimeFormatter的ofPattern靜態方法()傳入任何的模式,它會返回一個例項,這個模式的字面量與前例中是相同的。比如M代表月,m仍代表分,無效的模式會拋異常DateTimeParseException。

 

20、如何在java8中對日期進行格式化,轉換成字串

 前面的兩個例子中,我們主要是對日期字串來進行解析轉換成日期,在這個例子我們相反,是把日期轉換成字元。這裡我們有個LocalDateTime類的例項,我們要把他轉換成一個格式化好的日期串,與前例相同的是,我們仍需要制定模式串去建立一個DateTimeFormatter類的例項,但呼叫的是LocalDate.format()。這個方法會返回一個代表當前日期的字串,對應的模式就是傳入的DateTimeFormatter例項中定義好的。

java8中日期與時間API的幾個關鍵點

經過上面的例子,我們已經對java8的時間日期有了一定的瞭解,現在回顧一下

 

●它提供了javax.time.ZoneId用來處理時區。

●它提供了LocalDate與LocalTime類

●Java 8中新的時間與日期API中的所有類都是不可變且執行緒安全的,這與之前的Date與Calendar API中的恰好相反,那裡面像java.util.Date以及SimpleDateFormat這些關鍵的類都不是執行緒安全的。

●新的時間與日期API中很重要的一點是它定義清楚了基本的時間與日期的概念,比方說,瞬時時間,持續時間,日期,時間,時區以及時間段。它們都是基於ISO日曆體系的。

 

每個Java開發人員都應該至少了解這套新的API中的這五個類:

●Instant 它代表的是時間戳,比如2016-04-14T14:20:13.592Z,這可以從java.time.Clock類中獲取,像這樣: Instant current = Clock.system(ZoneId.of("Asia/Tokyo")).instant();

●LocalDate 它表示的是不帶時間的日期,比如2016-04-14。它可以用來儲存生日,週年紀念日,入職日期等。

●LocalTime - 它表示的是不帶日期的時間

●LocalDateTime - 它包含了時間與日期,不過沒有帶時區的偏移量

●ZonedDateTime - 這是一個帶時區的完整時間,它根據UTC/格林威治時間來進行時區調整

●這個庫的主包是java.time,裡面包含了代表日期,時間,瞬時以及持續時間的類。它有兩個子package,一個是java.time.foramt,這個是什麼用途就很明顯了,還有一個是java.time.temporal,它能從更低層面對各個欄位進行訪問。

●時區指的是地球上共享同一標準時間的地區。每個時區都有一個唯一識別符號,同時還有一個地區/城市(Asia/Tokyo)的格式以及從格林威治時間開始的一個偏移時間。比如說,東京的偏移時間就是+09:00。

●OffsetDateTime類實際上包含了LocalDateTime與ZoneOffset。它用來表示一個包含格林威治時間偏移量(+/-小時:分,比如+06:00或者 -08:00)的完整的日期(年月日)及時間(時分秒,納秒)。

●DateTimeFormatter類用於在Java中進行日期的格式化與解析。與SimpleDateFormat不同,它是不可變且執行緒安全的,如果需要的話,可以賦值給一個靜態變數。DateTimeFormatter類提供了許多預定義的格式器,你也可以自定義自己想要的格式。當然了,根據約定,它還有一個parse()方法是用於將字串轉換成日期的,如果轉換期間出現任何錯誤,它會丟擲DateTimeParseException異常。類似的,DateFormatter類也有一個用於格式化日期的format()方法,它出錯的話則會丟擲DateTimeException異常。

●再說一句,“MMM d yyyy”與“MMm dd yyyy”這兩個日期格式也略有不同,前者能識別出"Jan 2 2014"與"Jan 14 2014"這兩個串,而後者如果傳進來的是"Jan 2 2014"則會報錯,因為它期望月份處傳進來的是兩個字元。為了解決這個問題,在天為個位數的情況下,你得在前面補0,比如"Jan 2 2014"應該改為"Jan 02 2014"。

 

關於Java 8這個新的時間日期API就講到這了。這幾個簡短的示例 對於理解這套新的API中的一些新增類已經足夠了。我們學習瞭如何建立與修改日期例項。我們還了解了純日期,日期加時間,日期加時區的區別,知道如何比較兩個日期,如何找到某天到指定日期比如說下一個生日,週年紀念日或者保險日還有多少天。我們還學習瞭如何在Java 8中用執行緒安全的方式對日期進行解析及格式化,而無需再使用執行緒本地變數或者第三方庫這種取巧的方式。新的API能勝任任何與時間日期相關的任務。