1. 程式人生 > >【Java8新特性】關於Java8中的日期時間API,你需要掌握這些!!

【Java8新特性】關於Java8中的日期時間API,你需要掌握這些!!

## 寫在前面 > Java8之前的日期和時間API,存在一些問題,比如:執行緒安全的問題,跨年的問題等等。這些問題都在Hava8中的日期和時間API中得到了解決,而且Java8中的日期和時間API更加強大。立志成為架構師的你,必須掌握Java8中的日期和時間API。 ## 本地時間和時間戳 **主要方法:** - now:靜態方法,根據當前時間建立物件 - of:靜態方法,根據指定日期/時間建立物件 - plusDays,plusWeeks,plusMonths,plusYears:向當前LocalDate 物件新增幾天、幾周、幾個月、幾年 - minusDays,minusWeeks,minusMonths,minusYears:從當前LocalDate 物件減去幾天、幾周、幾個月、幾年 - plus,minus:新增或減少一個Duration 或Period - withDayOfMonth,withDayOfYear,withMonth,withYear:將月份天數、年份天數、月份、年份修改為指定的值並返回新的LocalDate 物件 - getDayOfYear:獲得年份天數(1~366) - getDayOfWeek:獲得星期幾(返回一個DayOfWeek列舉值) - getMonth:獲得月份, 返回一個Month 列舉值 - getMonthValue:獲得月份(1~12) - getYear:獲得年份 - until:獲得兩個日期之間的Period 物件,或者指定ChronoUnits 的數字 - isBefore,isAfter:比較兩個LocalDate - isLeapYear:判斷是否是閏年 ## 使用 LocalDate、 LocalTime、 LocalDateTime LocalDate、 LocalTime、 LocalDateTime 類的例項是不可變的物件,分別表示使用 ISO-8601日曆系統的日期、時間、日期和時間。它們提供了簡單的日期或時間,並不包含當前的時間資訊。也不包含與時區相關的資訊。 > 注: ISO-8601日曆系統是國際標準化組織制定的現代公民的日期和時間的表示法 | 方法 | 描述 | 示例 | | -------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | now() | 靜態方法,根據當前時間建立物件 | LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now(); | | of() | 靜態方法,根據指定日期/時間建立 物件 | LocalDate localDate = LocalDate.of(2016, 10, 26); LocalTime localTime = LocalTime.of(02, 22, 56); LocalDateTime localDateTime = LocalDateTime.of(2016, 10, 26, 12, 10, 55); | | plusDays, plusWeeks, plusMonths, plusYears | 向當前 LocalDate 物件新增幾天、 幾周、 幾個月、 幾年 | | | minusDays, minusWeeks, minusMonths, minusYears | 從當前 LocalDate 物件減去幾天、 幾周、 幾個月、 幾年 | | | plus, minus | 新增或減少一個 Duration 或 Period | | | withDayOfMonth, withDayOfYear, withMonth, withYear | 將月份天數、 年份天數、 月份、 年 份 修 改 為 指 定 的 值 並 返 回 新 的 LocalDate 物件 | | | getDayOfMonth | 獲得月份天數(1-31) | | | getDayOfYear | 獲得年份天數(1-366) | | | getDayOfWeek | 獲得星期幾(返回一個 DayOfWeek 列舉值) | | | getMonth | 獲得月份, 返回一個 Month 列舉值 | | | getMonthValue | 獲得月份(1-12) | | | getYear | 獲得年份 | | | until | 獲得兩個日期之間的 Period 物件, 或者指定 ChronoUnits 的數字 | | | isBefore, isAfter | 比較兩個 LocalDate | | | isLeapYear | 判斷是否是閏年 | | 示例程式碼如下所示。 ```java // 獲取當前系統時間 LocalDateTime localDateTime1 = LocalDateTime.now(); System.out.println(localDateTime1); // 執行結果:2019-10-27T13:49:09.483 // 指定日期時間 LocalDateTime localDateTime2 = LocalDateTime.of(2019, 10, 27, 13, 45,10); System.out.println(localDateTime2); // 執行結果:2019-10-27T13:45:10 LocalDateTime localDateTime3 = localDateTime1 // 加三年 .plusYears(3) // 減三個月 .minusMonths(3); System.out.println(localDateTime3); // 執行結果:2022-07-27T13:49:09.483 System.out.println(localDateTime1.getYear()); // 執行結果:2019 System.out.println(localDateTime1.getMonthValue()); // 執行結果:10 System.out.println(localDateTime1.getDayOfMonth()); // 執行結果:27 System.out.println(localDateTime1.getHour()); // 執行結果:13 System.out.println(localDateTime1.getMinute()); // 執行結果:52 System.out.println(localDateTime1.getSecond()); // 執行結果:6 LocalDateTime localDateTime4 = LocalDateTime.now(); System.out.println(localDateTime4); // 2019-10-27T14:19:56.884 LocalDateTime localDateTime5 = localDateTime4.withDayOfMonth(10); System.out.println(localDateTime5); // 2019-10-10T14:19:56.884 ``` ## Instant 時間戳 用於“時間戳”的運算。它是以Unix元年(傳統的設定為UTC時區1970年1月1日午夜時分)開始所經歷的描述進行運算 。 示例程式碼如下所示。 ```java Instant instant1 = Instant.now(); // 預設獲取UTC時區 System.out.println(instant1); // 執行結果:2019-10-27T05:59:58.221Z // 偏移量運算 OffsetDateTime offsetDateTime = instant1.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime); // 執行結果:2019-10-27T13:59:58.221+08:00 // 獲取時間戳 System.out.println(instant1.toEpochMilli()); // 執行結果:1572156145000 // 以Unix元年為起點,進行偏移量運算 Instant instant2 = Instant.ofEpochSecond(60); System.out.println(instant2); // 執行結果:1970-01-01T00:01:00Z ``` ## Duration 和 Period Duration:用於計算兩個“時間”間隔。 Period:用於計算兩個“日期”間隔 。 ```java Instant instant_1 = Instant.now(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Instant instant_2 = Instant.now(); Duration duration = Duration.between(instant_1, instant_2); System.out.println(duration.toMillis()); // 執行結果:1000 LocalTime localTime_1 = LocalTime.now(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } LocalTime localTime_2 = LocalTime.now(); System.out.println(Duration.between(localTime_1, localTime_2).toMillis()); // 執行結果:1000 ``` ```java LocalDate localDate_1 = LocalDate.of(2018,9, 9); LocalDate localDate_2 = LocalDate.now(); Period period = Period.between(localDate_1, localDate_2); System.out.println(period.getYears()); // 執行結果:1 System.out.println(period.getMonths()); // 執行結果:1 System.out.println(period.getDays()); // 執行結果:18 ``` ## 日期的操縱 TemporalAdjuster : 時間校正器。有時我們可能需要獲取例如:將日期調整到“下個週日”等操作。 TemporalAdjusters : 該類通過靜態方法提供了大量的常用 TemporalAdjuster 的實現。 例如獲取下個週日,如下所示: ```java LocalDate nextSunday = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); ``` 完整的示例程式碼如下所示。 ```java LocalDateTime localDateTime1 = LocalDateTime.now(); System.out.println(localDateTime1); // 2019-10-27T14:19:56.884 // 獲取這個第一天的日期 System.out.println(localDateTime1.with(TemporalAdjusters.firstDayOfMonth())); // 2019-10-01T14:22:58.574 // 獲取下個週末的日期 System.out.println(localDateTime1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY))); // 2019-11-03T14:22:58.574 // 自定義:下一個工作日 LocalDateTime localDateTime2 = localDateTime1.with(l -> { LocalDateTime localDateTime = (LocalDateTime) l; DayOfWeek dayOfWeek = localDateTime.getDayOfWeek(); if (dayOfWeek.equals(DayOfWeek.FRIDAY)) { return localDateTime.plusDays(3); } else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) { return localDateTime.plusDays(2); } else { return localDateTime.plusDays(1); } }); System.out.println(localDateTime2); // 執行結果:2019-10-28T14:30:17.400 ``` ## 解析與格式化 java.time.format.DateTimeFormatter 類:該類提供了三種格式化方法: * 預定義的標準格式 * 語言環境相關的格式 * 自定義的格式 示例程式碼如下所示。 ```java DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ISO_DATE; LocalDateTime localDateTime = LocalDateTime.now(); String strDate1 = localDateTime.format(dateTimeFormatter1); System.out.println(strDate1); // 執行結果:2019-10-27 // Date -> String DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String strDate2 = dateTimeFormatter2.format(localDateTime); System.out.println(strDate2); // 執行結果:2019-10-27 14:36:11 // String -> Date LocalDateTime localDateTime1 = localDateTime.parse(strDate2, dateTimeFormatter2); System.out.println(localDateTime1); // 執行結果:2019-10-27T14:37:39 ``` ## 時區的處理 Java8 中加入了對時區的支援,帶時區的時間為分別為:ZonedDate、 ZonedTime、 ZonedDateTime。 其中每個時區都對應著 ID,地區ID都為 “{區域}/{城市}”的格式,例如 : Asia/Shanghai 等。 * ZoneId:該類中包含了所有的時區資訊 * getAvailableZoneIds() : 可以獲取所有時區時區資訊 * of(id) : 用指定的時區資訊獲取 ZoneId 物件 示例程式碼如下所示。 ```java // 獲取所有的