java 时间api源码,Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析...

目录

0.前言

1.TemporalAccessor源码

2.Temporal源码

3.TemporalAdjuster源码

4.ChronoLocalDate源码

5.LocalDate源码

6.总结

0.前言

8d0bff066a01b423a2f309a66aa229f3.png

可以看出主要的LocalDate, LocalTime, LocalDateTime, Instant都是实现相同的接口,这里以LocalDate为例分析java8时间api源码,其他的类与LocalDate类似。

LocalDate的相关类图如下:完整类图

46f1186948f940c3a46d7f550f79522d.png

可以看出LocalDate同时实现了Temporal, TemporalAdjuster, ChronoLocalDate三个接口。

接口的默认方法:使用default 关键字给接口增加非抽象的方法实现,子类可以选择性实现。

静态方法:接口里可以声明静态方法,并且可以实现。

函数式接口:增加@FunctionalInterface 注解,只要这个接口只包含一个抽象方法。

1.TemporalAccessor源码

027d0531adfc5633ec1f9a6573655784.png

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 query(TemporalQuery query)

默认方法,这个日期-时间查询。它使用指定的查询策略对象查询此日期-时间。

2.Temporal源码

33a178b4bb88480a1e7960e30e226eb6.png

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源码

411945716da6aa93763234b8357af3fd.png

TemporalAdjuster接口加了函数式接口@FunctionalInterface注解,用于调整时间对象的策略。

(1)Temporal adjustInto(Temporal temporal)

调整指定的时间对象。

java.time.temporal.TemporalAdjusters 为常用的时间调节器,包含当月第一天,最后一天等等。

db939f98283ce20d9df672d977322e8d.png

方法说明:

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接口。

在任意年表中不包含(时间或时区)的日期,用于高级全球化用例。

3d812586f79c14c8f96e8ec3071166ef.png

从图中圈中部分可以看出 ChronoLocalDate实现了实现或重写了Temporal, TemporalAdjuster, Comparable接口。

其他方法:

(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修饰,线程安全,方法特别多,但很有规律。

类图如下:

d5e5fef84589f29ac759dd93fb549c2c.png

主要属性为:

/***最小日期:-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对象方法

68eae78ac8911f171f23a6886c591eac.png

例如:创建当前日期:

LocalDate now = LocalDate.now();

源码:可以看出是使用系统默认的Clock创建当前日期的。

public staticLocalDate now() {returnnow(Clock.systemDefaultZone());

}

(2)获取属性方法

8285e3736905c5f634d47c3e2e2f9c35.png

例如:获取年

int year = now.getYear();

源码:直接获取属性中year

public intgetYear() {returnyear;

}

(3)修改属性的方法

92276e52ff28dcc61e2f74750034d59a.png

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

LocalDate localDate1 = now.withYear(2020);

System.out.println(localDate1);

源码:可以看到底层,return new LocalDate(year, month, day); 创建了一个新对象。

public LocalDate withYear(intyear) {if (this.year ==year) {return this;

}

YEAR.checkValidValue(year);returnresolvePreviousValid(year, month, day);

}private static LocalDate resolvePreviousValid(int year, int month, intday) {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 newLocalDate(year, month, day);

}

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

d3b5b1e495ad178509b3c3a3fce8e109.png

例如:减少1年,输出:2018-12-26

LocalDate localDate2 = now.minusYears(1);

System.out.println(localDate2);

源码:可以看出底层使用了:plusYears(-yearsToSubtract),相当于+(-1)

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

}

(5)转换为各类DateTime(LocalDateTime、ZonedDateTime和OffsetDateTime)方法

94463b7d89d65c2a5429e68297bdd39f.png

例如:转为LocalDateTime 输出为:2019-12-26T00:00

LocalDateTime localDateTime =now.atStartOfDay();

System.out.println(localDateTime);

源码:this为当前的日期,LocalTime.MIDNIGHT为零点时间,组合为为LocalDateTime

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

}

(6)其他方法主要为实现ChronoLocalDate定义的方法

例如:ChronoLocalDate中定义的判断和比较方法

a3e62a242040af31893ad7e9921f8340.png

6.总结

TemporalAccessor主要定义了只读的获取属性方法,Temporal主要定义了修改日期属性和日期加减运算方法,ChronoLocalDate定义了国际化lDate的通用方法,LocalDate是ChronoLocalDate的ISO标准实现,实现了上述所有接口,final修饰,线程安全,方法定义明确,丰富多样,适用广。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值