【Java8新特性】06 新的日期和時間:LocalDate LocalTime LocalDateTime

Java8 由Oracle在2014年發佈,是繼Java5之後最具革命性的版本了。
Java8吸收其他語言的精髓帶來了函數式編程,lambda表達式,Stream流,新日期時間接口等一系列新特性,學會了這些新特性,可以讓你實現高效編碼、優雅編碼。

熱門精選文章,更多技術乾貨,微信搜索訂閱號【碼者圈】

【Java8新特性】01 函數式接口和Lambda表達式你真的會了嗎
【Java8新特性】02 函數式接口和Lambda表達式實戰練習:環繞執行模式使行爲參數化
【Java8新特性】03 Stream流式數據處理
【Java8新特性】04 詳解Lambda表達式中Predicate Function Consumer Supplier函數式接口
【Java8新特性】05 使用Optional取代null

1. Java8之前糟糕的日期時間API

(1) Date

java.util.Date類是Jdk 1.0引入的,易用性非常糟糕,比如年份的起始是1900年,月份的起始是0。比如要表示2019年6月18日,創建一個Date實例:

    Date date = new Date(119, 5, 18);

Date類已經不推薦使用了。

(2) Calendar

爲了解決Date糟糕的設計,Jdk 1.1 引入了java.util.Calendar類。不幸的是Calendar沒有扛起大任,仍然暴露出很多設計缺陷,導致寫代碼時容易出現問題,比如月份還是從0開始。

由於Date和Calendar推出的時間很接近,造成程序員對使用哪個類感到困惑。

還有一個很大的問題,Date和Calendar都是可變的類,這種設計會導致程序出現各種問題。

Date和Calendar的種種問題導致程序員們紛紛拋棄原生的jdk日期時間庫,轉投第三方組件如Joda-Time,Java設計者似乎意識到這個問題,在借鑑Joda-Time的基礎上終於在Java8版本中加入了新的日期時間包java.time.*

2. Java8 新的日期時間API

(1)日期時間常用類

針對日期和時間,Java8提供了LocalDate, LocalTime, LocalDateTime, Instant等常用類。Instant類是機器容易理解的類,通常以毫秒等整數值對時間進行建模。

創建實例常見操作:

// 當前日期
LocalDate date1 = LocalDate.now();
// 指定日期
LocalDate date2 = LocalDate.of(2019, 6, 18);
LocalDate date3 = LocalDate.of(2019, Month.JULY, 18);

// 當前時間
LocalTime time1 = LocalTime.now();
// 指定時間
LocalTime time2 = LocalTime.of(21, 10, 59);

// 當前日期時間
LocalDateTime dateTime1 = LocalDateTime.now();
// 指定日期時間
LocalDateTime dateTime2 = LocalDateTime.of(2019, 6, 18, 21, 10, 59);

// 當前時間戳
Instant instant1 = Instant.now();
// 指定時間戳
Instant instant2 = Instant.ofEpochMilli(1000000L);

(2)時間計算

可以用plus,minus對時間日期進行操作:

LocalDate today = LocalDate.of(2019, 6, 18);
LocalDate tomorrow = today.plus(1L, ChronoUnit.DAYS);
System.out.println(tomorrow); // output: 2019-06-19
LocalDate yesterday = today.minus(1L, ChronoUnit.DAYS);
System.out.println(yesterday); // output: 2019-06-17

你還可以通過Duration計算兩個時間的間隔:

Duration duration = Duration.between(dateTime2, dateTime1);
System.out.println(duration.toHours()); // output: 841

Period通過用來計算兩個日期之間的間隔:

Period period = Period.between(date2, date1);
System.out.println(period.toTotalMonths()); // output: 1

Duration和Period還包含了很多實用的方法如from,of等,大家可以自行看源碼進行學習。

(3)時間解析和格式化

LocalDate,LocalTime,LocalDateTime都有parse靜態方法用來解析給定的時間日期串:

// 時間日期解析
LocalDateTime parsedDateTime = LocalDateTime.parse("2019/06/18 12:11:10",
        DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
System.out.println(parsedDateTime); // output: 2019-06-18T12:11:10

時間格式化可以使用java8提供的新類DateTimeFormatter,java8之前的SimpleDateFormat不推薦大家再用了。

// 時間日期格式化
LocalDateTime dateTime = LocalDateTime.now();
// 使用自定義formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dateTime.format(formatter)); // output: 2019-07-23 23:09:19
// 使用系統自帶formatter
System.out.println(dateTime.format(DateTimeFormatter.ISO_DATE_TIME)); // output: 2019-07-23T23:09:19.31

(4)時區使用方法

java8之前使用java.util.TimeZone類處理時區,java8新增ZoneId替代TimeZone。

ZoneId實例化方法:

ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZoneId zoneId2 = ZoneId.systemDefault();

老時區對象轉化爲新時區:

ZoneId zoneId3 = TimeZone.getDefault().toZoneId();

帶時區的時間表示方法:

LocalDateTime dateTime2 = LocalDateTime.of(2019, 6, 18, 21, 10, 59);

ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZonedDateTime zonedDateTime = dateTime2.atZone(zoneId);
// output: 2019-06-18T21:10:59+08:00[Asia/Shanghai]
System.out.println(zonedDateTime);

ZoneId zoneId2 = ZoneId.systemDefault();
ZonedDateTime zonedDateTime2 = dateTime2.atZone(zoneId2);
// output: 2019-06-18T21:10:59+08:00[Asia/Shanghai]
System.out.println(zonedDateTime2);

3. 總結

LocalDate, LocalTime, LocalDateTime, ZoneId之間的關係可以用一張圖解釋:
java8日期時間關係圖
【碼者圈】屬於編碼者自己的圈子,掃描二維碼關注,第一時間獲取更多技術乾貨!
掃描關注碼者圈

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