java8 Date/Time API 新的日期處理工具

接上篇文章 java8 新特性 由於上篇過於龐大,使得重點不夠清晰,本篇單獨拿出 java8 的 Date/Time api 進行說明,新的日期時間工具全部都在 java.time 及其子包中。

新 Date/Time API 設計原則

Java 8日期/時間API是 JSR-310 規範的實現,它的目標是克服舊的日期/時間API實現中所有的缺陷,新的日期/時間API的一些設計原則如下:

  • 不變性:新的日期/時間API中,所有的類都是不可變的,這種設計有利於併發編程。
  • 關注點分離:新的API將人可讀的日期時間和機器時間(unix timestamp)明確分離,它爲日期(Date)、時間(Time)、日期時間(DateTime)、時間戳(unix timestamp)以及時區定義了不同的類。
  • 清晰:在所有的類中,方法都被明確定義用以完成相同的行爲。舉個例子,要拿到當前實例我們可以使用now()方法,在所有的類中都定義了format()和parse()方法,而不是像以前那樣專門有一個獨立的類。爲了更好的處理問題,所有的類都使用了工廠模式和策略模式,一旦你使用了其中某個類的方法,與其他類協同工作並不困難。
  • 實用操作:所有新的日期/時間API類都實現了一系列方法用以完成通用的任務,如:加、減、格式化、解析、從日期/時間中提取單獨部分等操作。
  • 可擴展性:新的日期/時間API是工作在ISO-8601日曆系統上的,但我們也可以將其應用在非IOS的日曆上。

常用類及其使用

時間大致可以分爲三個部分:日期、時間、時區;其中日期又細分爲年、月、日;時間又細分爲時、分、秒

一般機器時間用從 1970-01-01T00:00 到現在的秒數來表示時間; 這裏糾正大部分人犯的一個錯誤概念,時間戳指的是秒數,而不是毫秒數。

幾乎所有的時間對象都實現了 Temporal 接口,所以接口參數一般都是 Temporal

  • Instant: 表示時間線上的一個點,參考點是標準的Java紀元(epoch),即1970-01-01T00:00:00Z(1970年1月1日00:00 GMT)
  • LocalDate: 日期值對象如 2019-09-22
  • LocalTime:時間值對象如 21:25:36
  • LocalDateTime:日期+時間值對象
  • ZoneId:時區
  • ZonedDateTime:日期+時間+時區值對象
  • DateTimeFormatter:用於日期時間的格式化
  • Period:用於計算日期間隔
  • Duration:用於計算時間間隔

Instant 表示時間線上的一個點(瞬時)

// 測試執行一個 new 操作使用的時間(納秒值)
Instant begin = Instant.now();
StreamMain streamMain = new StreamMain();
Instant end = Instant.now();
System.out.println(Duration.between(begin,end).toNanos());

LocalDateLocalTimeLocalDateTimeZonedDateTime 可以規爲一組,用於表示時間的

// 可以使用 of 方法構建它們的實例,如下面創建了一個 2019-9-22 21:42:59 東八區 的時間對象 
LocalDate localDate = LocalDate.of(2019, Month.SEPTEMBER, 22);
LocalTime localTime = LocalTime.of(21, 42, 59);
LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());

// 獲取現在的時間,這是一個靜態方法
LocalDate now = LocalDate.now();

// 每個實例可以獲取它們的 part 信息,如獲取年 
int year = localDate.getYear();

// 可以修改 part 信息,這將返回一個新對象,如增加一年
LocalDate localDatePlus = localDate.plusYears(1);

// 設置 part 信息,也會返回新的對象,如設置爲 2017 年 
LocalDate localDateWithYear = localDate.withYear(2017);

// 比較兩個日期 isAfter,isBefore
boolean after = localDate.isAfter(LocalDate.now());

// 格式化日期時間
// yyyy-MM-dd
System.out.println(now.format(DateTimeFormatter.ISO_DATE));
// yyyy-MM-ddTHH:mm:ss
System.out.println(now.format(DateTimeFormatter.ISO_DATE_TIME));
// yyyy-MM-dd HH:mm:ss
System.out.println(now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)));

// 日期解析 
System.out.println(LocalDate.parse("2019-09-22"));
System.out.println(LocalDateTime.parse("2019-09-22T21:05:22"));
System.out.println(LocalDateTime.parse("2019-09-22 21:05:22",DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)));

ZoneId 用來操作時區,它提供了獲取所有時區和本地時區的方法

ZoneId zoneId = ZoneId.systemDefault();
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();

PeriodDuration 可以視爲一組,用於計算時間間隔

// 創建一個兩週的間隔
Period periodWeeks = Period.ofWeeks(2);

// 一年三個月零二天的間隔
Period custom = Period.of(1, 3, 2);

// 一天的時長
Duration duration = Duration.ofDays(1);

// 計算2015/6/16 號到現在 2019/09/22 過了多久,它這個把間隔分到每個 part 了
LocalDate now = LocalDate.now();
LocalDate customDate = LocalDate.of(2015, 6, 16);
Period between = Period.between(customDate, now);
// 結果爲 4:3:6 即過去了 4年3個月6天了
System.out.println(between.getYears()+":"+between.getMonths()+":"+between.getDays());

// 比較兩個瞬時的時間間隔 
Instant begin = Instant.now();
Instant end = Instant.now();
Duration.between(begin,end);

// 同樣可以修改 part 信息和設置 part 信息,都是返回新的對象來表示設置過的值,原來的對象不變
Period plusDays = between.plusDays(1);
Period withDays = between.withDays(4);

與 Date,Calendar 的轉換

雖然說,這個新的時間工具很好用,但如果不能與以前的舊的 api 兼容的話,一樣是沒有用的;還好新的工具類能很好的與以前的工具類進行相互轉換。

通過 Instant做中間轉換實現DateCalendarLocalDateTimeZonedDateTimeLocalDate 的互相轉換

// LocalDateTime 轉 Date
Date localDateTimeDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
// LocalDateTime 轉 Calendar
Calendar localDateTimeCalendar = GregorianCalendar.from(ZonedDateTime.of(localDateTime, ZoneId.systemDefault()));

// Date 轉 LocalDateTime
LocalDateTime dateLocalDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
// Calendar 轉 LocalDateTime
LocalDateTime calendarLocalDateTime = LocalDateTime.ofInstant(calendar.toInstant(), ZoneOffset.systemDefault());

相關源碼位置

https://gitee.com/sanri/example/tree/master/testjava8

一點小推廣

創作不易,希望可以支持下我的開源軟件,及我的小工具,歡迎來 gitee 點星,fork ,提 bug 。

Excel 通用導入導出,支持 Excel 公式
博客地址:https://blog.csdn.net/sanri1993/article/details/100601578
gitee:https://gitee.com/sanri/sanri-excel-poi

使用模板代碼 ,從數據庫生成代碼 ,及一些項目中經常可以用到的小工具
博客地址:https://blog.csdn.net/sanri1993/article/details/98664034
gitee:https://gitee.com/sanri/sanri-tools-maven

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