新的日期和時間API

簡述Date歷史

JAVA1.0時代,對日期和時間的支持只能依賴java.util.Date類。該類只能以毫秒的精度來表示時間。該類在使用時存在如下不適合的地方:年份的起始選擇是1900年、月份的起始從0開始、toString的返回值中甚至還包含了JVM的默認時區CET。

JAVA1.1時代,Date類中的很多方法被廢棄了,取而代之的是java.util.Calendar類。Calendar類也有類似的問題:月份依舊是從0開始計算(不過,至少Calendar類拿掉了由1900年開始計算年份這一設計)。

另外,DateFormat方法不是線程安全的。

最後就是Date和Calendar類都是可以變的。

LocalDate和LocalTime

LocalDate類的實例是一個不可變對象,它只提供日期信息,不提供時間信息。另外,它也不附帶任何與時區相關的信息。用戶可以通過靜態工廠方法LocalDate.of創建一個LocalDate實例。

LocalTime類的實例是一個不可變對象,它只提供時間信息,不提供日期信息。另外,它也不附帶任何與時區相關的信息。用戶可以通過靜態工廠方法LocalTime.of創建一個LocalTime實例。

LocalDate/LocalTime可以通過LocalDate.parse/LocalTime.
parse傳入字符串/DateTimeFormatter來解析,不過,一旦傳遞的字符串參數無法被解析爲合法的LocalDate/LocalTime對象,這兩個parse方法都會拋出一個繼承自RuntimeException的DateTimeParseException異常。

LocalDateTime

LocalDateTime是LocalDate和LocalTime的合體。它同時表示了日期和時間,但不帶有時區信息。

可以用LocalDateTime.of直接創建,也可以通過LocalDateTime.of合併日期和時間對象來構造。

可以通過LocalTime.atDate/LocalDate.atTime創建一個LocalDateTime對象。

可以使用toLocalDate/toLocalTime方法,從LocalDateTime中提取LocalDate/LocalTime組件。

機器的日期Instant

從計算機的角度來看,建模時間最自然的格式是表示一個持續時間段上某個點的單一大整型數。這也是新的java.time.Instant類對時間建模的方式,基本上它是以Unix元年時間(傳統的設定爲UTC時區1970年1月1日午夜時分)開始所經歷的秒數進行計算。

可以通過向靜態工廠方法Instant.ofEpochSecond傳遞一個代表秒數的值來創建一個該類的實例。

靜態工廠方法Instant.ofEpochSecond還有一個增強的重載版本,它接收第二個以納秒爲單位的參數值,對傳入作爲秒數的參數進行調整(增/減)。重載的版本會調整納秒參數,確保保存的納秒分片在0到999 999 999之間。

靜態工廠方法Instant.now可以獲取當前時刻的時間戳。

最後的最後,Instant設計初衷是爲了便於機器使用。它包含的是由秒、納秒所構成的數字。所以,它無法處理那些我們非常容易理解的時間單位。

差值Duration/Period

Duration:比較兩個LocalTimes對象、兩個LocalDateTimes對象、兩個Instant對象之間的差值。

Period:比較N個LocalTimes對象、N個LocalDateTimes對象、N個Instant對象之間的差值。

Duration和Period類都提供了很多非常方便的工廠類,直接創建對應的實例,而不需要通過比較兩個對象來生成:

Duration.ofMinutes(3);返回Duration對象

Duration.of(3, ChronoUnit.MINUTES);返回Duration對象

Period.ofDays(10);返回Period對象

Period.ofWeeks(3);返回Period對象

Period.of(2, 6, 1);返回Period對象

修改對象

如果你已經有一個LocalDate對象,想要創建它的一個修改版,最直接也最簡單的方法是使用withAttribute方法。 withAttribute方法會創建對象的一個副本,並按照需要修改它的屬性。注意:所有withAttribute方法都返回一個修改了屬性的對象。它們都不會修改原來的對象。

LocalDate date1 = LocalDate.of(2014, 3, 18);

LocalDate date2 = date1.withYear(2011);

LocalDate date3 = date2.withDayOfMonth(25);

LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 9);

LocalDate/LocalTime/LocalDateTime/Instant都實現了Temporal接口,所有的日期和時間API類都實現了get/with方法,使用get和with方法,可以將Temporal對象值的讀取和修改區分開。如果Temporal對象不支持請求訪問的字段,它會拋出一個UnsupportedTemporalTypeException異常。

與get和with方法類似,plus和minus方法都聲明於Temporal接口中。通過這些方法,對TemporalUnit對象加上或者減去一個數字,我們能非常方便地將Temporal對象前溯或者回滾至某個時間段,通過ChronoUnit枚舉我們可以非常方便地實現TemporalUnit接口。

LocalDate date1 = LocalDate.of(2014, 3, 18);

LocalDate date2 = date1.plusWeeks(1);

LocalDate date3 = date2.minusYears(3);

LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS);

TemporalAdjuster

在使用with方法時,爲了更加方便的跳轉到某個特定日期,可以使用TemporalAdjuster。API裏面包含了很多封裝好了大 量 預 定 義 的TemporalAdjuster。可以通過TemporalAdjuster類的靜態工廠方法訪問:

dayOfWeekInMonth 創建一個新的日期,它的值爲同一個月中每一週的第幾天

firstDayOfMonth 創建一個新的日期,它的值爲當月的第一天

firstDayOfNextMonth 創建一個新的日期,它的值爲下月的第一天

firstDayOfNextYear 創建一個新的日期,它的值爲明年的第一天

firstDayOfYear 創建一個新的日期,它的值爲當年的第一天

firstInMonth 創建一個新的日期,它的值爲同一個月中,第一個符合星期幾要求的值

lastDayOfMonth 創建一個新的日期,它的值爲當月的最後一天

lastDayOfNextMonth 創建一個新的日期,它的值爲下月的最後一天

lastDayOfNextYear 創建一個新的日期,它的值爲明年的最後一天

lastDayOfYear 創建一個新的日期,它的值爲今年的最後一天

lastInMonth 創建一個新的日期,它的值爲同一個月中,最後一個符合星期幾要求的值

next/previous創建一個新的日期,並將其值設定爲日期調整後或者調整前,第一個符合指定星期幾要求的日期

nextOrSame/previousOrSame創建一個新的日期,並將其值設定爲日期調整後或者調整前,第一個符合指定星期幾要求的日期,如果該日期已經符合要求,直接返回該對象

格式化日期

新的java.time.format包就是爲這個目的而設計的。最重要的類是DateTimeFormatter。創建格式器最簡單的方法是通過它的靜態工廠方法以及常量。

比如BASIC_ISO_DATE和ISO_LOCAL_DATE這樣的常量是 DateTimeFormatter 類的預定義實例。所有的DateTimeFormatter實例都能用於以一定的格式創建代表特定日期或時間的字符串:

LocalDate date = LocalDate.of(2014, 3, 18);

String s1 = date.format(DateTimeFormatter.
BASIC_ISO_DATE);其日期格式爲:20140318

String s2 = date.format(DateTimeFormatter.
ISO_LOCAL_DATE);其日期格式爲:2014-03-18

注意:所有的DateTimeFormatter實例都是線程安全的。因此能夠以單例模式創建格式器實例,能在多個線程間共享實例。

DateTimeFormatter類還支持一個靜態工廠方法,它可以按照某個特定的模式創建格式器:DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");

DateTimeFormatter italianFormatter =DateTimeFormatter
.ofPattern("d. MMMM yyyy", Locale.ITALIAN);

如果你還需要更加細粒度的控制,DateTimeFormatterBuilder類還提供了更復雜的格式器。它提供了非常強大的解析功能,比如區分大小寫的解析、柔性解析(允許解析器使用啓發式的機制去解析輸入,不精確地匹配指定的模式)、填充,以及在格式器中指定可選節 。

處理不同的時區

時區的處理是新版日期和時間API新增加的重要功能,使用新版日期和時間API時區的處理被極大地簡化了。

新的java.time.ZoneId類是老版java.util.TimeZone的替代品。

跟其他日期和時間類一樣, ZoneId類也是無法修改的。ZoneId對象可以將與LocalDate、 LocalDateTime或者是Instant對象整合起來。

注意

 

JAVA8

JAVA8之前

一週從週一開始,數字從1-7

一週從週日開始,數字從1-7

月份從1月開始,數字從1-12

月份從1月開始,數字從0-11

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章