目录

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修饰,线程安全,方法定义明确,丰富多样,适用广。

Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析的更多相关文章

  1. netty中的发动机--EventLoop及其实现类NioEventLoop的源码分析

    EventLoop 在之前介绍Bootstrap的初始化以及启动过程时,我们多次接触了NioEventLoopGroup这个类,关于这个类的理解,还需要了解netty的线程模型.NioEventLoo ...

  2. 🏆【Alibaba中间件技术系列】「RocketMQ技术专题」让我们一起探索一下DefaultMQPushConsumer的实现原理及源码分析

    RocketMQ的前提回顾 RocketMQ是一款分布式.队列模型的消息中间件,具有以下特点: 能够保证严格的消息顺序 提供丰富的消息拉取模式 高效的订阅者水平扩展能力 实时的消息订阅机制 亿级消息堆 ...

  3. java String类 trim() 方法源码分析

    public String trim() {        int arg0 = this.value.length;   //得到此字符串的长度        int arg1 = 0;   //声 ...

  4. Servlet容器Tomcat中web.xml中url-pattern的配置详解[附带源码分析]

    目录 前言 现象 源码分析 实战例子 总结 参考资料 前言 今天研究了一下tomcat上web.xml配置文件中url-pattern的问题. 这个问题其实毕业前就困扰着我,当时忙于找工作. 找到工作 ...

  5. Java线程池ThreadPoolExector的源码分析

    前言:线程是我们在学习java过程中非常重要的也是绕不开的一个知识点,它的重要程度可以说是java的核心之一,线程具有不可轻视的作用,对于我们提高程序的运行效率.压榨CPU处理能力.多条线路同时运行等 ...

  6. 鸿蒙内核源码分析(时间管理篇) | 谁是内核基本时间单位 | 百篇博客分析OpenHarmony源码 | v35.02

    百篇博客系列篇.本篇为: v35.xx 鸿蒙内核源码分析(时间管理篇) | 谁是内核基本时间单位 | 51.c.h .o 本篇说清楚时间概念 读本篇之前建议先读鸿蒙内核源码分析(总目录)其他篇. 时间 ...

  7. ABP源码分析四十五:ABP ZERO中的EntityFramework模块

    AbpZeroDbContext:配置ABP.Zero中定义的entity的Dbset EntityFrameworkModelBuilderExtensions:给PrimitiveProperty ...

  8. heapster源码分析——kubelet的api调用分析

    一.heapster简介 什么是Heapster? Heapster是容器集群监控和性能分析工具,天然的支持Kubernetes和CoreOS.Kubernetes有个出名的监控agent---cAd ...

  9. Vue3中的响应式对象Reactive源码分析

    Vue3中的响应式对象Reactive源码分析 ReactiveEffect.js 中的 trackEffects函数 及 ReactiveEffect类 在Ref随笔中已经介绍,在本文中不做赘述 本 ...

随机推荐

  1. 洛谷 P5569 [SDOI2008]石子合并 GarsiaWachs算法

    石子合并终极通用版 #include<bits/stdc++.h> using namespace std ; ]; int n,t,ans; void combine(int k) { ...

  2. 题解【POJ3252】Round Numbers

    Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, P ...

  3. (c#)删除链表中的节点

    题目 解: 解析: n1→n2→n3→n4删除n2即将n2更改成n3n1→n3(n2)→n4

  4. Module build failed: TypeError: this.getResolve is not a function at Object.loader sass报错!(亲测有效!~~)

    vue安装node-sass编译报错 在搭建vue脚手架 或者是在vue项目中,想使用sass的功能,需先安装如下 npm install node-sass --save-dev //安装node- ...

  5. linux下删除空行的几种方法

    在查看linux下的配置文件时,为了便于一目了然的查看,经常会删除空行和#头的行.而linux在删除空行的方法很多,grep.sed.awk.tr等工具都能实现.现总结如下: 1.grep grep ...

  6. java把带小数点的字符串转换成int类型

    String number ="1.0000"; int num =Double.valueOf(number).intValue();//转换为Int类型

  7. opencv:自适应阈值

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...

  8. [杭电_HDU] 2013

    #include <iostream> using namespace std; int main() { int n; while (cin >> n) { ; //最终桃子 ...

  9. Eclipse C++配置静态链接库和动态链接库

    转:https://blog.csdn.net/iteye_20658/article/details/82650699 1.动态库: 一.创建动态链接库1.创建工程new->project-& ...

  10. Python学习(七)——匿名函数、map函数、filter函数、reduce函数与其他内置函数

    匿名函数 lambda x: x + 1 # lambda:定义匿名函数的关键字 # x:形参 # x+1:程序处理逻辑 fun = lambda x: x + 1 print(fun(5)) #6 ...