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());
LocalDate
、LocalTime
、LocalDateTime
、ZonedDateTime
可以規為一組,用於表示時間的
// 可以使用 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();
Period
,Duration
可以視為一組,用於計算時間間隔
// 建立一個兩週的間隔
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
做中間轉換實現Date
,Calendar
與 LocalDateTime
,ZonedDateTime
,LocalDate
的互相轉換
// 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-ma