Java日期時間API系列8-----Jdk8中java.time包中的新的日期時間API類的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修飾,線程安全,方法定義明確,豐富多樣,適用廣。


免責聲明!

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



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