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類中類圖以下:html

 

能夠看出主要的LocalDate, LocalTime, LocalDateTime, Instant都是實現相同的接口,這裏以LocalDate爲例分析java8時間api源碼,其餘的類與LocalDate相似。java

  LocalDate的相關類圖以下:完整類圖api

能夠看出LocalDate同時實現了Temporal, TemporalAdjuster, ChronoLocalDate三個接口。安全

java.time包是在jdk8中上添加進來的,jdk8接口有了一些新的特性:接口的默認方法、靜態方法和函數式接口框架

接口的默認方法:使用default 關鍵字給接口增長非抽象的方法實現,子類能夠選擇性實現。函數

靜態方法:接口裏能夠聲明靜態方法,而且能夠實現。this

函數式接口:增長@FunctionalInterface 註解,只要這個接口只包含一個抽象方法。spa

更多描述能夠參考Java 8 指南:http://www.javashuo.com/article/p-qlsghjuj-b.html線程

 

1.TemporalAccessor源碼

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

這是日期、時間和偏移量對象的基本接口類型。它是由那些能夠提供信息的類實現的,好比{@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修飾,線程安全,方法定義明確,豐富多樣,適用廣。

相關文章
相關標籤/搜索