jdk8新特性之八日期時間API


引言

java 8通過發布新的Date-Time API進一步加強對日期與時間的處理。在舊版的java中,日期時間APi存在諸多問題。java 8引入的新的一系列API,對時間日期處理提供了更好的支持,清楚的定義了時間日期的一些概念,比如說,瞬時時間(Instant),持續時間(duration),日期(date),時間(time),時區(time-zone)以及時間段(Period)。同時,借鑒了Joda庫的一些優點,比如將人和機器對時間日期的理解區分開的。

java8新特性

  1. jdk8新特性之一Lambda表達式
  2. jdk8新特性之二方法引用
  3. jdk8新特性之三函數式接口
  4. jdk8新特性之四默認方法
  5. jdk8新特性之五Stream API
  6. jdk8新特性之六Optional類
  7. jdk8新特性之七Nashorn JavaScript
  8. jdk8新特性之八日期時間API
  9. jdk8新特性之九Base64

舊版日期時間API的問題

  • 非線程安全:java.uttil.Date 是非線程安全的,所有的日期類都是可變的,這是java日期類最大的問題之一。
  • 設計很差:java的日期/時間類的定義並不一致,在java.util和java.sql的包中毒有日期類,此外用於格式化和解析的類在java.text包中定義。java.util.Date同時包含日期和時間,而java.sql.Date僅包含日期,將其納入java.sql包並不合理。另外這兩個類都有相同提高的名字,這本身就是一個非常糟糕的設計。
  • 時區處理麻煩:日期類並不提供國際化,沒有時區支持,因此java引入了java.util.Caleandar和java.util.TimeZone類,但他們同樣存在上述所有的問題。

新日期時間API

java8在java.time包下提供了很多新的API。以下為兩個比較重要的API:

  • Local(本地):簡化了日期時間的處理,沒有時區的問題。
  • Zoned(時區):通過制定的時區處理日期時間。
    具體的API:
  • LocalDate:存儲不包含時間的日期,比如2020-01-11。可以用來存儲生日,周年紀念日,入職日期等。
  • LocalTime:存儲不包含日期的時間,比如11:07:03.580。

LocalDate-日期

只存儲年月日。格式:2020-01-11

創建LocalDate對象

//獲取當前日期
LocalDate currDate=LocalDate.now();
System.out.println("當前日期:"+currDate);
//指定日期
LocalDate noeDay=LocalDate.of(2020, 1, 11);
System.out.println("當前日期:"+noeDay);
//通過字符串指定日期
LocalDate towDay=LocalDate.parse("2020-01-11");
System.out.println("當前日期:"+towDay);

運行結果輸出:

當前日期:2020-01-11
當前日期:2020-01-11
當前日期:2020-01-11

獲取年月日周

// 年
int year = currDate.getYear();
// 月
int month = currDate.getMonthValue();
// 一月的第幾天
int day = currDate.getDayOfMonth();
// 一周的第幾天
int week = currDate.getDayOfWeek().getValue();
System.out.printf("%d年%d月%d日,星期%d%n", year, month, day, week);

運行結果輸出:

2020年1月11日,星期6

比較兩個日期是否相同

LocalDate重寫了equals方法,讓日期的比較也變得簡單了。

LocalDate date1  = LocalDate.parse("2020-01-11");
LocalDate date2  = LocalDate.parse("2020-01-11");
System.out.println("比較兩個日期是否相同:"+date1.equals(date2));

運行結果輸出:

比較兩個日期是否相同:true

日期前后比較

//isBefore在之前
boolean isBefore=LocalDate.parse("2020-01-11").isBefore(LocalDate.parse("2020-01-10"));
//isAfter在之后
boolean isAfter=LocalDate.parse("2020-01-11").isAfter(LocalDate.parse("2020-01-10"));

日期加減

System.out.println("當前時間"+LocalDate.now());
System.out.println("當前時間加1天"+LocalDate.now().plusDays(1));
System.out.println("當前時間加1月"+LocalDate.now().plusMonths(1));
System.out.println("當前時間加1年"+LocalDate.now().plusYears(1));

運行結果輸出:

當前時間2020-01-11
當前時間加1天2020-01-12
當前時間加1月2020-02-11
當前時間加1年2021-01-11

LocalTime-時間

存儲不包含日期的時間,比如11:07:03.580。

LocalTime和LocalDate類似,區別在於LocalDate不包含具體時間,而LocalTime包含具體時間。同樣可以使用now、of或parse方法來獲得對象。

LocalTime time = LocalTime.now();
LocalTime time2 =LocalTime.of(11, 7,3);
LocalTime time3 =LocalTime.parse("11:07:03");

LocalDate類似它也擁有isBefore、isAfter、獲取時間單元等方法,就不再贅述。

需要注意的是,LocalTime獲得的時間格式為:11:41:58.904。也就是,HH:mm:ss.nnn,這里nnn是納秒。

還有一個在實戰中查詢日期區間時我們經常定義的“23:59:59.99”常量再也不用自己定義了。

//最大時間23:59:59.999999999
LocalTime maxTime =LocalTime.MAX;
//最小時間00:00
LocalTime minTime =LocalTime.MIN;

LocalDateTime-日期和時間的組合

LocalDateTime表示日期和時間組合。同樣可以使用now、of或parse方法來獲得對象。

LocalDateTime datetime=LocalDateTime.now();
LocalDateTime datetime2=LocalDateTime.of(2020, 1,11,11,54,30);
LocalDateTime datetime3=LocalDateTime.parse("2020-01-11T12:35");

也可以調用LocalDate的atTime()方法或LocalTime的atDate()方法將LocalDate或LocalTime合並成一個LocalDateTime。

LocalDateTime datetime4=LocalDate.now().atTime(LocalTime.now());
LocalDateTime datetime5=LocalTime.now().atDate(LocalDate.now());

LocalDateTime與LocalDate和LocalTime之間可以相互轉化。其他日期增減等操作與上面的類似。

Instant-時間戳

用於“時間戳”的運算。它是以Unix元年(傳統的設定為UTC時區1970年1月1日午夜時分)開始所經歷的描述進行運算。

// 默認獲取UTC時區
Instant instant=Instant.now();
System.out.println("當前時間(UTC時區):"+instant);
System.out.println("獲取時間戳:"+instant.toEpochMilli());
		
// 偏移量運算
OffsetDateTime offsetDateTime =instant.atOffset(ZoneOffset.ofHours(8));
System.out.println("當前時間:"+offsetDateTime);
		
// 以Unix元年為起點,進行偏移量運算
Instant instant2 = Instant.ofEpochSecond(60);
System.out.println(instant2);

運行結果輸出為:

當前時間(UTC時區):2020-01-11T05:55:35.493Z
獲取時間戳:1578722135493
當前時間:2020-01-11T13:55:35.493+08:00
1970-01-01T00:01:00Z

Duration-獲取時間段

Duration的內部實現與Instant類似,但Duration表示時間段,通過between方法創建。

LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
Duration duration=Duration.between(from, to);
		
//總天數
long days=duration.toDays();
//小時
long hours=duration.toHours();
//分鍾
long millis=duration.toMillis();
//秒數
long seconds=duration.getSeconds();
//毫秒數
long minutes=duration.toMinutes();
//納秒數
long nanos=duration.toNanos();
System.out.println("天數"+days);
System.out.println("小時"+hours);
System.out.println("分鍾"+millis);
System.out.println("秒數"+seconds);
System.out.println("毫秒數"+minutes);
System.out.println("納秒數"+nanos);

運行結果輸出:

天數1
小時24
分鍾86400000
秒數86400
毫秒數1440
納秒數86400000000000

Duration對象還可以通過of()方法創建,該方法參數為時間段長度和時間單位。

// 7天
Duration duration1 = Duration.of(7, ChronoUnit.DAYS);
// 60秒
Duration duration2 = Duration.of(60, ChronoUnit.SECONDS);

Period-獲取日期段

Period與Duration類似,獲取一個時間段,只不過單位為年月日,也可以通過of方法和between方法創建,between方法接收的參數為LocalDate。

Period period=Period.of(2020, 1, 11);
Period period1 = Period.between(LocalDate.now(), LocalDate.now().plusYears(1));

ZonedDateTime-創建時區時間

ZonedDateTime類,用於處理帶時區的日期和時間。ZoneId表示不同的時區。大約有40不同的時區。

Set<String> allZoneIds=ZoneId.getAvailableZoneIds();

創建時區:

ZoneId zoneId=ZoneId.of("Asia/Shanghai");

把LocalDateTime轉換成特定的時區:

ZonedDateTime zonedDateTime=ZonedDateTime.of(LocalDateTime.now(), zoneId);

獲取當前時區:

//獲取當前時區
ZoneId z=ZoneId.systemDefault();

獲取日期時間:

ZonedDateTime dd = ZonedDateTime.now();
ZonedDateTime date1 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]");

時間日期格式化

Java8對日期的格式化操作非常簡單,首先看到上面的類大多都提供了parse方法,可以直接通過解析字符串得到對應的對象。

而日期和時間的格式化可通過LocalDateTime的format方法進行格式化。

LocalDateTime dateTime=LocalDateTime.now();
String str=dateTime.format(DateTimeFormatter.ISO_DATE_TIME);
System.out.println(str);
str = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(str);

可以使用DateTimeFormatter預置的格式,也可以通過DateTimeFormatter.ofPattern方法來指定格式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM