天天看點

大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結

2 Java 8中的DateTimeFormatter

2.1 格式化字元串

首先,使用DateTimeFormatterBuilder定義格式化字元串,無需死記大寫Y還是小寫y,大寫M還是小寫m:

大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結

2.2 線程安全

可定義為static使用

2.3 待解析字元串和格式不比對時就報錯

大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結
  • 日志
2020/11/11 11:11:11.789
Exception in thread "main" java.time.format.DateTimeParseException: Text '20201111' could not be parsed at index 0
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777)
    at org.javaedge.time.commonmistakes.datetime.dateformat.CommonMistakesApplication.better(CommonMistakesApplication.java:96)
    at org.javaedge.time.commonmistakes.datetime.dateformat.CommonMistakesApplication.main(CommonMistakesApplication.java:47)      

3 Java8計算日期時間

  • 有人喜歡使用時間戳進行計算,比如希望得到目前時間後30天:把

    new Date().getTime

    得到的時間戳加30天對應毫秒數
  • 大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結
  • 得到的日期居然比目前日期還要早,根本不是後30天
  • 大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結
  • 因為int發生了溢出!。
  • 應将30改為30L,使其為long:
  • 大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結
  • 正确輸出
  • 大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結
  • Java 8前代碼,建議使用Calendar:
  • 大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結
  • 使用Java 8的日期時間類型,可以直接進行各種計算,更加簡潔和友善:
  • 大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結
  • 對日期時間做計算操作,日期時間API會比Calendar功能強大很多。

3.1 minus/plus直接對日期加減

大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結

3.2 with快捷時間調節

TemporalAdjusters.firstDayOfMonth得到目前月的第一天

TemporalAdjusters.firstDayOfYear()得到目前年的第一天

TemporalAdjusters.previous(DayOfWeek.SATURDAY)得到上一個周六

TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)得到本月最後一個周五

大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結

3.3 使用lambda自定義的時間調整

  • 為目前時間增加100天以内的随機天數:
  • 大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結

判斷日期是否符合某個條件

大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結

query查詢是否比對條件

大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結

使用Java 8操作和計算日期時間雖然友善,但計算兩個日期差時可能會踩坑:Java 8中有一個專門的類Period定義了日期間隔,通過Period.between得到了兩個LocalDate的差,傳回的是兩個日期差幾年零幾月零幾天。

如果希望得知兩個日期之間差幾天,直接調用Period的getDays()方法得到的隻是最後的“零幾天”,而不是算總的間隔天數。

比如,計算2020年12月12日和2020年10月1日的日期間隔,很明顯日期差是2個月零11天,但擷取getDays方法得到的結果隻是11天,而不是72天:

大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結

可使用ChronoUnit.DAYS.between解決這個問題:

大廠都是怎麼用Java8代替SimpleDateFormat?(下)2 Java 8中的DateTimeFormatter3 Java8計算日期時間4 總結

4 總結

也許你認為java.util.Date類似于新API中的LocalDateTime。其實不是,雖然它們都沒時區概念

java.util.Date類是因為使用UTC表示,是以沒有時區概念,其本質是時間戳

LocalDateTime,嚴格上可以認為是一個日期時間的表示,而不是一個時間點

是以,在把Date轉換為LocalDateTime的時候,需要通過Date的toInstant方法得到一個UTC時間戳進行轉換,并需要提供目前的時區,這樣才能把UTC時間轉換為本地日期時間(的表示)。反過來,把LocalDateTime的時間表示轉換為Date時,也需要提供時區,用于指定是哪個時區的時間表示,也就是先通過atZone方法把LocalDateTime轉換為ZonedDateTime,然後才能獲得UTC時間戳:

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());      

有人說新API很麻煩,還需要考慮時區,真麻煩。但并非因為API強行設計繁瑣,而是UTC時間要變為當地時間,必須考慮時區!