JDK8新特性:日期時間相關API
舊版日期時間API存在的問題:
- 1.設計很差:在
java.tilogjava sq|
的包中都有日期類,java.util.Date
同時包含日期和時間,而java.sql.Date
僅。包含日期。此外用於格式化和解析的類在java.text
包中定義。 - 2.非線程安全:
java.util.Date
是非線程安全的,所有的日期類都是可變的,這是Java日期類最大的問題之一。 - 3.時區處理麻煩:日期類並不提供國際化,沒有時區支持。因此ava引入了
java.util.Calendar
和java.util.TimeZone
類, 但他們同樣存在上述所有的問題。
新日期時間API介紹
JDK 8中增加了一套全新的日期時間API,這套API設計合理,是線程安全的。
- java.time - 包含值對象的基礎包
- java.time.chrono - 提供不同日曆系統的訪問
- java.time.format - 格式化和解析時間和日期
- java.time.temporal - 包含底層框架和擴展特性
- java.time.zone - 包含時區支持的類
新的日期及時間API位於java.time包中,下面是一些關鍵類:
- LocalDate:表示日期,包含年月日.格式爲2019-10-16
- LocalTime:表示時間,包含時分秒,格式爲16:38:54.158549300
- LocalDateTime:表示日期時間,包含年月日,時分秒,格式爲2018-09-06T15:33:56.750
- DateTimeFormatter:日期時間格式化類。
- Instant:時間戳,表示一個特定的時間瞬間。
- Duration:用於計算2個時間(LocalTime, 時分秒)的距離
- Period:用於計算2個日期(LocalDate, 年月日)的距離
- zonedDaterime:包含時區的時間
Java中使用的歷法是ISO 8601日曆系統,它是世界民用曆法,也就是我們所說的公曆。平年有365天.閏年是366天。此外ava 8還提供了4套其他曆法,分別是:
- ThaiBuddhistDate: 泰國佛教歷
- MinguoDate: 中華民國曆
- JapaneseDate:日本歷
- HijrahDate: 伊斯蘭曆
LocalDateTime、LocalDate、LocalTime常用方法
LocalDateTime = LocalDate + LocalTime
(1.)獲取默認時區的當前時間
LocalDate localdate = LocalDate.now(); --獲取時間:年月日
LocalTime localtime = LocalTime.now(); --獲取時間:時分秒
LocalDateTime localdatetime = LocalDateTime.now(); --獲取時間:年月日時分秒
--結果:
localdate = 2020-06-16
localtime = 17:35:13.788
localdatetime = 2020-06-16T17:35:13.789
(2)指定具體的日期時間
LocalDateTime dateTime = LocalDateTime.of(2089, 12, 25, 12, 30, 30); -- 年月日時分秒
LocalDate date = LocalDate.of(2089, 12, 25); -- 年月日
LocalTime time1 = LocalTime.of(12, 30); -- 時分
LocalTime time2 = LocalTime.of(12, 30, 30); -- 時分秒
LocalTime time3 = LocalTime.of(12, 30, 30, 150); -- 時分秒納秒
-- 結果
dateTime:2089-12-25T12:30:30
date:2089-12-25
time1:12:30
time2:12:30:30
time3:12:30:30.000000150
(3)獲取具體的年月日時分秒、星期、天數等
這裏爲 LocalDate
和 LocalTime
分開使用,也可以直接使用 LocalDateTime
LocalDate of = LocalDate.now();
System.out.println("年 = " + of.getYear());
System.out.println("月(英文) = " + of.getMonth());
System.out.println("月(數字) = " + of.getMonthValue());
System.out.println("這個月的第幾天 = " + of.getDayOfMonth());
System.out.println("一年中的第幾天 = " + of.getDayOfYear());
System.out.println("星期 = " + of.getDayOfWeek());
LocalTime nowTime = LocalTime.now();
System.out.println("時:" + nowTime.getHour());
System.out.println("分:" + nowTime.getMinute());
System.out.println("秒:" + nowTime.getSecond());
System.out.println("納秒:" + nowTime.getNano());
(4)日期大小判斷
這裏的 isBefore
和 isAfter
比較都是後一個減去前一個,如果後面一個大,返回的是正數,否則是負數
LocalDate date1 = LocalDate.of(2020, 11, 30);
LocalDate date2 = LocalDate.of(2089, 12, 25);
System.out.println(date1.isBefore(date2));
System.out.println(date1.isAfter(date2));
System.out.println(date1.equals(date2));
System.out.println(date.isLeapYear()); -- 是否是閏年
(5)某個月或者某年有多少天
System.out.println(date1.lengthOfMonth()); -- 判斷這個月有多少天
System.out.println(date1.lengthOfYear()); -- 判斷年份有多少天
(6)直接修改、增加、減少年月日時分秒
-- 修改
LocalDateTime dateTime1 = LocalDateTime.of(2089, 12, 25, 12, 30, 30);
System.out.println("設置年份:" + dateTime1.withYear(1991));
System.out.println("設置月份:" + dateTime1.withMonth(5));
System.out.println("設置小時:" + dateTime1.withHour(3));
System.out.println("設置分鐘:" + dateTime1.withMinute(25));
System.out.println("設置秒:" + dateTime1.withSecond(26));
System.out.println("設置這個月的第多少天:" + dateTime1.withDayOfMonth(20));
System.out.println("設置這一年的第多少天:" + dateTime1.withDayOfYear(100));
-- 增加
System.out.println("增加年:" + dateTime1.plusYears(3));
System.out.println("增加月:" + dateTime1.plusMonths(5));
System.out.println("增加天:" + dateTime1.plusDays(3));
System.out.println("增加小時:" + dateTime1.plusHours(2));
System.out.println("增加分鐘:" + dateTime1.plusMinutes(26));
System.out.println("增加秒:" + dateTime1.plusSeconds(20));
-- 減少
System.out.println("減少年:" + dateTime1.minusYears(3));
System.out.println("減少月:" + dateTime1.minusMonths(5));
System.out.println("減少天:" + dateTime1.minusDays(3));
System.out.println("減少小時:" + dateTime1.minusHours(2));
System.out.println("減少分鐘:" + dateTime1.minusMinutes(26));
System.out.println("減少秒:" + dateTime1.minusSeconds(20));
(7)時間類型轉換
LocalDateTime dateTime1 = LocalDateTime.of(2089, 12, 25, 12, 30, 30);
LocalDate date = LocalDate.of(2089, 12, 25);
LocalTime time= LocalTime.of(12, 30, 30);
System.out.println(dateTime1.toLocalTime()); -- LocalDateTime轉LocalTime
System.out.println(dateTime1.toLocalDate()); -- LocalDateTime轉LocalDate
System.out.println(date.atTime(time)); -- LocalDate和LocalTime轉LocalDateTime
System.out.println(time.atDate(date)); -- LocalDate和LocalTime轉LocalDateTime
-- 結果
12:30:30
2089-12-25
2089-12-25T12:30:30
2089-12-25T12:30:30
日期解析和格式化:DateTimerFormatter
LocalDateTime dateTime = LocalDateTime.of(2089, 12, 25, 12, 30, 30);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-- 正反都能調用format方法
String date1 = dateTime.format(dtf);
System.out.println(date1);
String date2 = dtf.format(dateTime);
System.out.println(date2);
-- 結果
2089-12-25 12:30:30
2089-12-25 12:30:30
計算日期時間差 Duration 和 Period
- Duration
LocalDateTime today = LocalDateTime.now();
LocalDateTime dateTime = LocalDateTime.of(2089, 12, 25, 12, 30, 30);
Duration duration = Duration.between(today, dateTime);
System.out.println(duration.toDays()); -- 相差的天數
System.out.println(duration.toHours()); -- 相差的小時數
System.out.println(duration.toMinutes()); -- 相差的分鐘數
System.out.println(duration.toMillis()); -- 相差的毫秒數
System.out.println(duration.toNanos()); -- 相差的納秒數
- Period
LocalDate today = LocalDate.now();
LocalDate date = LocalDate.of(2089, 12, 25);
Period period = Period.between(today, date);
System.out.println(period.getYears()); -- 相差多少年
System.out.println(period.getMonths()); -- 相差多少月
System.out.println(period.getDays()); -- 相差多少天
時間調整器:TemporalAdjuster 和 TemporalAdjusters
TemporalAdjuster
是函數式接口,可自定義調整;
TemporalAdjusters
是針對 TemporalAdjuster
的工具類,內置了很多方法
例子:
-- 調整到下一年的第一天
LocalDateTime dateTime = LocalDateTime.of(2089, 12, 25, 12, 30, 30);
LocalDateTime with = dateTime.with(TemporalAdjusters.firstDayOfNextYear());
System.out.println("with = " + with);
-- 結果
with = 2090-01-01T12:30:30
時間戳:Instant
Instant instant = Instant.now(); -- 得到當前時間到 1970-01-01 00:00:00 的毫秒值
System.out.println(instant);
System.out.println("秒數:" + instant .getEpochSecond());
System.out.println("毫秒數:" + instant .toEpochMilli());
這裏的 Instant.now()
方法默認使用UTC時間,而不是系統默認時間。點進源碼即可看到
時區相關:ZoneID、ZonedDateTime
--獲取世界各個地方的時區集合
ZoneId.getAvailableZoneIds().forEach(System.out::println);
ZonedDateTime now = ZonedDateTime.now();-- 系統默認時區
ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());-- 標準時區 UTC
ZonedDateTime now2 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));--通過ZoneId指定時區
System.out.println("now = " + now);
System.out.println("now1 = " + now1);
System.out.println("now2 = " + now2);