☕【Java技術指南】「Java8編程專題」讓你真正會用對Java新版日期時間API編程指南

語言: CN / TW / HK

theme: smartblue

小知識,大挑戰!本文正在參與“程序員必備小知識”創作活動。

技術背景

一切都源於JSR-310規範

  • JSR-310規範提供一個新的和改進的Java日期與時間API,會在Java8中包含,可以下載OpenJDK早期發佈版本試用,詳細信息可見:https://jdk8.java.net/download.html

  • JSR-310規範領導者Stephen Colebourne就是joda-time作者,其主要思想也是借鑑了joda-time,而不是直接把joda-time移植到Java平台中,API是類似的,但做了改進和調整。

  • 具體規範請前往如下地址下載:https://jcp.org/en/jsr/detail?id=310

代替Date類的日期類(LocalXX系列)

首當其衝的是LocalDateTime、LocalDate、LocalTime ,提供了對java.util.Date的替代,另外還提供了新的DateTimeFormatter用於對格式化/解析的支持

  • 介紹相關的XXX.now()的方法,這些太簡單了,接下來介紹一下相關的較為特殊的用法,例如:

相對於ZoneId.systemDefault()默認時區

java LocalDateTime now = LocalDateTime.now(); System.out.println(now);

相當於使用默認時區時鐘瞬時時間創建`Clock.systemDefaultZone()``;

相對於自定義時區

java LocalDateTime now2= LocalDateTime.now(ZoneId.of("Europe/Paris")); System.out.println(now2);

會以相應的時區顯示日期:歐洲的巴黎時區

自定義時鐘

java Clock clock = Clock.system(ZoneId.of("Asia/Dhaka")); LocalDateTime now3= LocalDateTime.now(clock); System.out.println(now3);

與上面的一樣,會以相應的時區顯示日期

定義時間數據

不需要寫什麼相對時間 如java.util.Date 年是相對於1900 月是從0開始

java //2013-12-31 23:59 LocalDateTime d1 = LocalDateTime.of(2013, 12, 31, 23, 59); java //年月日 時分秒 納秒 LocalDateTime d2 = LocalDateTime.of(2013, 12, 31, 23, 59,59, 11);

使用瞬時時間 + 時區

java Instant instant = Instant.now(); LocalDateTime d3 = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()); System.out.println(d3);

解析String->LocalDateTime

java LocalDateTime d4 = LocalDateTime.parse("2013-12-31T23:59"); System.out.println(d4);

999毫秒 等價於999000000納秒

java LocalDateTime d5 = LocalDateTime.parse("2013-12-31T23:59:59.999"); System.out.println(d5);

使用DateTimeFormatter API 解析和格式化

java DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); LocalDateTime d6 = LocalDateTime.parse("2013/12/31 23:59:59", formatter); System.out.println(formatter.format(d6));

時間屬性的獲取

java System.out.println(d6.getYear()); //獲取年份 System.out.println(d6.getMonth()); //獲取月份 System.out.println(d6.getDayOfYear()); // 獲取當年的第幾天 System.out.println(d6.getDayOfMonth());//獲取屬於本月的第幾天 System.out.println(d6.getDayOfWeek());// 獲取相對於本週的日期 System.out.println(d6.getHour());// 小時 System.out.println(d6.getMinute()); //分鐘 System.out.println(d6.getSecond()); // 秒數 System.out.println(d6.getNano()); //納秒數

時間增減

java LocalDateTime d7 = d6.minusDays(1); LocalDateTime d8 = d7.plus(1, IsoFields.QUARTER_YEARS);

代替System.currentTimeMillis()的瞬時對象(Instant)

瞬時時間,等價於以前的System.currentTimeMillis()

  • 瞬時時間 相當於以前的System.currentTimeMillis()

java Instant instant1 = Instant.now(); //精確到秒 得到相對於1970-01-01 00:00:00 UTC的一個時間 System.out.println(instant1.getEpochSecond()); //精確到毫秒 System.out.println(instant1.toEpochMilli());

  • 獲取系統UTC默認時鐘
    java Clock clock1 = Clock.systemUTC(); //得到時鐘的瞬時時間 Instant instant2 = Instant.now(clock1); System.out.println(instant2.toEpochMilli());

  • 固定瞬時時間時鐘 java Clock clock2 = Clock.fixed(instant1, ZoneId.systemDefault()); Instant instant3 = Instant.now(clock2);//得到時鐘的瞬時時間 System.out.println(instant3.toEpochMilli());//與上面的 instant1代表的含義一樣!

Clock時鐘

類似於鐘錶的概念,提供瞭如系統時鐘、固定時鐘、特定時區的時鐘

//時鐘提供給我們用於訪問某個特定 時區的 瞬時時間、日期和時間的。

系統默認UTC時鐘(當前瞬時時間 System.currentTimeMillis())

java Clock c1 = Clock.systemUTC(); System.out.println(c1.millis()); //每次調用將返回當前瞬時時間(UTC)

系統默認時區時鐘(當前瞬時時間)

java Clock c2 = Clock.systemDefaultZone(); Clock c31 = Clock.system(ZoneId.of("Europe/Paris")); //巴黎時區 System.out.println(c31.millis()); //每次調用將返回當前瞬時時間(UTC)

java Clock c32 = Clock.system(ZoneId.of("Asia/Shanghai"));//上海時區 System.out.println(c32.millis());//每次調用將返回當前瞬時時間(UTC)

java Clock c4 = Clock.fixed(Instant.now(), ZoneId.of("Asia/Shanghai"));//固定上海時區時鐘 System.out.println(c4.millis()); Thread.sleep(1000); System.out.println(c4.millis()); //不變 即時鐘時鐘在那一個點不動

java Clock c5 = Clock.offset(c1, Duration.ofSeconds(2)); //相對於系統默認時鐘兩秒的時鐘 System.out.println(c1.millis()); System.out.println(c5.millis());

ZonedDateTime

  • 帶有時區的date-time 存儲納秒、時區和時差(避免與本地date-time歧義);API和LocalDateTime類似。

  • API和LocalDateTime類似,只是多了時差(如2013-12-20T10:35:50.711+08:00[Asia/Shanghai])

java ZonedDateTime now = ZonedDateTime.now(); System.out.println(now);

java ZonedDateTime now2= ZonedDateTime.now(ZoneId.of("Europe/Paris")); System.out.println(now2);

其他的用法也是類似的 就不介紹了

java ZonedDateTime z1 = ZonedDateTime.parse("2013-12-31T23:59:59Z[Europe/Paris]"); System.out.println(z1);

Duration

表示兩個瞬時時間的時間段

```java Duration d1 = Duration.between(Instant.ofEpochMilli(System.currentTimeMillis() - 12323123), Instant.now()); //得到相應的時差 System.out.println(d1.toDays());
System.out.println(d1.toHours());
System.out.println(d1.toMinutes());
System.out.println(d1.toMillis());
System.out.println(d1.toNanos());

//1天時差 類似的還有如ofHours()
Duration d2 = Duration.ofDays(1);
System.out.println(d2.ofHours()); ```

Calendar的替代者Chronology

Chronology用於對年曆系統的支持,是java.util.Calendar的替代者

java //提供對java.util.Calendar的替換,提供對年曆系統的支持 Chronology c = HijrahChronology.INSTANCE; ChronoLocalDateTime d = c.localDateTime(LocalDateTime.now()); System.out.println(d);

年、年月、月日、週期的API支持

java Year year = Year.now(); YearMonth yearMonth = YearMonth.now(); MonthDay monthDay = MonthDay.now(); System.out.println(year);//年 System.out.println(yearMonth); //年-月 System.out.println(monthDay); // 月-日

Period 日期層面的間隔時間

週期,如表示10天前 3年5個月

java Period period1 = Period.ofDays(10); System.out.println(period1); Period period2 = Period.of(3, 5, 0); System.out.println(period2);

參考文章

http://www.codedata.com.tw/java/jodatime-jsr310-1-date-calendar/ http://www.codedata.com.tw/java/jodatime-jsr310-2-time-abc/ http://www.codedata.com.tw/java/jodatime-jsr310-3-using-jodatime/

「其他文章」