Java日期時間API系列8-----Jdk8中java.time包中的新的日期時間API類的LocalDate源碼分析

来源:https://www.cnblogs.com/xkzhangsanx/archive/2019/12/27/12081148.html
-Advertisement-
Play Games

Jdk8中java.time包中的新的日期時間API類的LocalDate源碼分析,TemporalAccessor、Temporal、TemporalAdjuster、ChronoLocalDate和LocalDate的關係解析。 ...


目錄

0.前言

1.TemporalAccessor源碼

2.Temporal源碼

3.TemporalAdjuster源碼

4.ChronoLocalDate源碼

5.LocalDate源碼

6.總結

 

0.前言

  通過前面Java日期時間API系列6-----Jdk8中java.time包中的新的日期時間API類中類圖如下:

 

可以看出主要的LocalDate, LocalTime, LocalDateTime, Instant都是實現相同的介面,這裡以LocalDate為例分析java8時間api源碼,其他的類與LocalDate類似。

  LocalDate的相關類圖如下:完整類圖

可以看出LocalDate同時實現了Temporal, TemporalAdjuster, ChronoLocalDate三個介面。

java.time包是在jdk8中上添加進來的,jdk8介面有了一些新的特性:介面的預設方法、靜態方法和函數式介面

介面的預設方法:使用default 關鍵字給介面增加非抽象的方法實現,子類可以選擇性實現。

靜態方法:介面里可以聲明靜態方法,並且可以實現。

函數式介面:增加@FunctionalInterface 註解,只要這個介面只包含一個抽象方法。

更多描述可以參考Java 8 指南:https://www.cnblogs.com/xkzhangsanx/p/10847284.html

 

1.TemporalAccessor源碼

TemporalAccessor是框架級介面,定義對時態對象(如日期、時間、偏移量或它們的某些組合)的只讀訪問。

這是日期、時間和偏移量對象的基本介面類型。它是由那些可以提供信息的類實現的,比如{@linkplain TemporalField欄位}或{@linkplain TemporalQuery查詢}。

(1)boolean isSupported(TemporalField field)

檢查是否支持指定的欄位

(2)default ValueRange range(TemporalField field)

預設方法,獲取指定欄位的有效值範圍

(3)default int get(TemporalField field)

這個方法為預設方法,以int的形式獲取指定欄位的值

(4)long getLong(TemporalField field)

以long的形式獲取指定欄位的值

(5)default <R> R query(TemporalQuery<R> query)

預設方法,這個日期-時間查詢。它使用指定的查詢策略對象查詢此日期-時間。

 

2.Temporal源碼

 Temporal繼承TemporalAccessor介面。

Temporal也是框架級介面,定義對時態對象(如日期、時間、偏移量或它們的某些組合)的讀寫訪問。

這是日期、時間和偏移量對象的基本介面類型,這些對象足夠完整,可以使用加減操作。

(1)boolean isSupported(TemporalUnit unit)

檢查是否支持指定的單元

(2)default Temporal with(TemporalAdjuster adjuster)

預設方法,返回調整後的對象

例如:

date = date.with(lastDayOfMonth());

返回當前月的最後一天

(3)Temporal with(TemporalField field, long newValue)

根據指定的欄位更改

(4)default Temporal plus(TemporalAmount amount)

預設方法,增加指定時間

(5)Temporal plus(long amountToAdd, TemporalUnit unit)

根據指定的單位增加時間

(6)default Temporal minus(TemporalAmount amount)

預設方法,減少指定時間

(7)default Temporal minus(long amountToSubtract, TemporalUnit unit)

預設方法,根據指定的單元減少時間

(8)long until(Temporal endExclusive, TemporalUnit unit)

根據指定的單元計算到另一個時間的相差值

例如:

        LocalDate localDate = LocalDate.of(2019, 1, 1);
        LocalDate endDate = LocalDate.of(2019, 1, 16);
        long days = localDate.until(endDate, ChronoUnit.DAYS);
        System.out.println(days);

輸出:15

3.TemporalAdjuster源碼

 

TemporalAdjuster介面加了函數式介面@FunctionalInterface註解,用於調整時間對象的策略。

(1)Temporal adjustInto(Temporal temporal)

調整指定的時間對象。

java.time.temporal.TemporalAdjusters 為常用的時間調節器,包含當月第一天,最後一天等等。

方法說明:

dayOfWeekInMonth   同一個月中每一周的第幾天
firstDayOfMonth     當月的第一天
firstDayOfNextMonth   下月的第一天
firstDayOfNextYear   明年的第一天
firstDayOfYear     當年的第一天
firstInMonth          同一個月中,第一個符合星期幾要求的值
lastDayOfMonth     當月的最後一天
lastDayOfNextMonth   下月的最後一天
lastDayOfNextYear   明年的最後一天
lastDayOfYear   今年的最後一天
lastInMonth   同一個月中,最後一個符合星期幾要求的值
next/previous  將其值設定為日期調整後或者調整前,第一個符合指定星期幾要求的日期
nextOrSame/previousOrSame  將其值設定為日期調整後或者調整前,第一個符合指定星
期幾要求的日期,如果該日期已經符合要求,直接返回該對象

 例如:當月最後一天

temporal = temporal.with(lastDayOfMonth());

 

4.ChronoLocalDate源碼

ChronoLocalDate 介面 繼承了Temporal, TemporalAdjuster, Comparable<ChronoLocalDate>介面。

在任意年表中不包含(時間或時區)的日期,用於高級全球化用例。

從圖中圈中部分可以看出 ChronoLocalDate實現了實現或重寫了Temporal, TemporalAdjuster, Comparable<ChronoLocalDate>介面。

其他方法:

(1)default boolean isLeapYear()

預設方法,計算閏年

(2)int lengthOfMonth()

根據日曆系統的定義,返回由這個日期表示的月份的長度。

(3)default int lengthOfYear()

預設方法,返回由日曆系統定義的日期表示的年份長度。

(4)default long toEpochDay()

預設方法,返回1970-01-01開始的天數

(5)default int compareTo(ChronoLocalDate other)

預設方法,實現介面Comparable,比較大小

(6)default boolean isAfter(ChronoLocalDate other)

是否在other後面

(7)default boolean isBefore(ChronoLocalDate other)

是否在other前面

(8)default boolean isEqual(ChronoLocalDate other)

是否與other相等

(9)object介面相關的方法:

boolean equals(Object obj)

int hashCode()

String toString()

(10)static ChronoLocalDate from(TemporalAccessor temporal)

從時態對象獲取ChronoLocalDate的實例。

(11)default ChronoLocalDateTime<?> atTime(LocalTime localTime)

將這個日期和時間組合起來,創建一個ChronoLocalDateTime。

(12)default String format(DateTimeFormatter formatter)

ChronoLocalDate 格式化處理

(13)Chronology getChronology()

獲取此日期的年表

(14)default Era getEra()

獲取由年表定義的年代

 

5.LocalDate源碼

LocalDate同時實現了Temporal, TemporalAdjuster, ChronoLocalDate三個介面,是ChronoLocalDate介面國際化的ISO-8601標準實現,final修飾,線程安全,方法特別多,但很有規律。

類圖如下:

主要屬性為:

/**
*最小日期:-999999999-01-01
*/
public static final LocalDate MIN = LocalDate.of(Year.MIN_VALUE, 1, 1); 

/**
*最d大日期:+999999999-12-31
*/
public static final LocalDate MAX = LocalDate.of(Year.MAX_VALUE, 12, 31);

/**
*400年周期中的天數
*/
private static final int DAYS_PER_CYCLE = 146097;

/**
*從0年到1970年的天數
*/
static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L);

/**
*年
*/
private final int year;

/**
*月
*/
private final short month;

/**
*日
*/
private final short day;

主要方法,除了實現Temporal, TemporalAdjuster, ChronoLocalDate三個介面還添加了一些特有的方法。所有可以分為6類方法:

(1)創建LocalDate對象方法

 例如:創建當前日期:

LocalDate now = LocalDate.now();

源碼:可以看出是使用系統預設的Clock創建當前日期的。

    public static LocalDate now() {
        return now(Clock.systemDefaultZone());
    }

 

 (2)獲取屬性方法

 例如:獲取年

int year = now.getYear();

源碼:直接獲取屬性中year

    public int getYear() {
        return year;
    }

 

 (3)修改屬性的方法

 例如:修改年,輸出:2020-12-26

        LocalDate localDate1 = now.withYear(2020);
        System.out.println(localDate1);

源碼:可以看到底層,return new LocalDate(year, month, day); 創建了一個新對象。

    public LocalDate withYear(int year) {
        if (this.year == year) {
            return this;
        }
        YEAR.checkValidValue(year);
        return resolvePreviousValid(year, month, day);
    }


private static LocalDate resolvePreviousValid(int year, int month, int day) {
        switch (month) {
            case 2:
                day = Math.min(day, IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                day = Math.min(day, 30);
                break;
        }
        return new LocalDate(year, month, day);
    }

 

 (4)增加或減少日期方法

 例如:減少1年,輸出:2018-12-26

        LocalDate localDate2 = now.minusYears(1);
        System.out.println(localDate2);

源碼:可以看出底層使用了:plusYears(-yearsToSubtract),相當於+(-1)

    public LocalDate minusYears(long yearsToSubtract) {
        return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract));
    }

 

(5)轉換為各類DateTime(LocalDateTime、ZonedDateTime和OffsetDateTime)方法

 例如:轉為LocalDateTime 輸出為:2019-12-26T00:00

        LocalDateTime localDateTime = now.atStartOfDay();
        System.out.println(localDateTime);

源碼:this為當前的日期,LocalTime.MIDNIGHT為零點時間,組合為為LocalDateTime

    public LocalDateTime atStartOfDay() {
        return LocalDateTime.of(this, LocalTime.MIDNIGHT);
    }

 

 (6)其他方法主要為實現ChronoLocalDate定義的方法

例如:ChronoLocalDate中定義的判斷和比較方法

   

6.總結

  TemporalAccessor主要定義了只讀的獲取屬性方法,Temporal主要定義了修改日期屬性和日期加減運算方法,ChronoLocalDate定義了國際化lDate的通用方法,LocalDate是ChronoLocalDate的ISO標準實現,實現了上述所有介面,final修飾,線程安全,方法定義明確,豐富多樣,適用廣。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv ...
  • ...
  • 今天在改一個看似很簡單以前也經常遇到的一個bug發現了很多問題。實際結果肯定沒有想象的那麼簡單。所以我想總結一下:保證下次不會踩坑。 業務場景是點擊一個按鈕,會產生一個彈框。重覆快速的點擊多次,會產生多個彈框。那麼這個問題該怎麼解決呢? 1. 函數防抖節流 這兩個東西我不知道看過了多少文檔,可到現在 ...
  • 高德地圖技術團隊希望打造一套快速精準的UI解決方案,通過自動化的方式生產UI代碼,解放研發生產力的同時滿足客戶需求。 ...
  • [TOC] 簡單工廠模式缺陷 "大白話簡單工廠模式(Simple Factory Pattern)" 中通過買車的經歷解釋了簡單工廠模式。但熟悉設計模式的朋友會發現一些問題。 工廠類集中了所有實例(產品)的創建邏輯,一旦這個工廠不能正常工作,整個系統都會受到影響。用日產車工廠的例子來形容就是日產汽車 ...
  • 微服務改造是一個長期過程,這個過程會遇到各式各樣的問題,方法論可以幫助我們更好地解決這些問題,並且降低風險。緊接昨天的上篇《如何把單體式應用拆解成微服務?【上】》,今天我們一起來看看具體的拆解場景。 ...
  • socketserver、struct模塊練習,簡易的FTP ...
  • 這幾個變數判斷函數在PHP開發中用的其實挺多的,而且粗看上去都差不多,但其實還是有不少的區別的,如果搞不清楚,也許就會遺留一些潛在的bug, 包括我自已也遇到過這樣的坑,比如有一次我就遇到過用empty判斷出現的問題,前端是允許輸入0的,但是我用empty判斷的話就為真,我就直接給報錯了,所以這裡就 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...