📫 作者简介:「六月暴雪飞梨花」,专注于研究Java,就职于科技型公司后端工程师
🏆 近期荣誉:华为云云享专家、阿里云专家博主
🔥 三连支持:欢迎 ??关注、👍点赞、👉收藏三连,支持一下博主~
Java里的日期和时间格式化问题,在JDK8(Java SE Development Kit8,以下使用过程中,均称为JDK1.8或者JDK8)以前有很多问题,例如日期类并不提供国际化,没有时区支持,包分配的也比较混乱。所以在JDK8后进行了大改造,索性在rt.jar中新增了一个time包,这样我们就可以个性化设置日期时间的展示方式了。
目前JDK已经到达了JDK 21(Java Development Kit 21),但是在主流的市场上面,使用JDK8的居多。我们现在已经掌握了不少关于日期和时间的操作技巧,但其实随着时间的不断推移,现实的需求也在不断更新,原先的一些API已经难以满足开发需求了。所以从JDK 8之后,为了满足更多的开发需求,Java给我们增加了不少关于日期时间的新特性,接下来本篇文章就带各位来看看这些新特性有哪些。
其他的就不在介绍那么多了,相关的介绍可以参考上两篇文章:LocalDate和LocalTime的详细剖析以及用法都进行了实践,而将LocalDateTime放在最后是因为,他在某些层面上是将上述两个进行了合体以及变相衍生了一些使用方法,所以熟悉上述两个用法后,再来看最后一个类的用法,就很轻松理解。其实三个日期、时间类都是在一起:LocalDate、LocalTime、LocalDateTime
,主要是需要先了解前两个,但是我们在实际使用过程中,LocalDate和LocalDateTime却是使用频率最高,也是最长使用的两个类。
Time API是一组对日期和时间的最重要方面进行建模的包。java. time包中的核心类使用ISO-8601中定义的日历系统(基于公历系统)作为默认日历。当我们引入JDK8后,可以在rt.jar中的java.time目录下找到对应的基础API,打开可以看到有很多新引入的包和类。功能虽多,但是常用的也就是那么几个,所以你想要尽快熟悉,可以自行点击进去查阅,这也是每次写这里都要将这个拿出来,希望大家可以多点击下源码,你会收到不一样的开心。
LocalDateTime是一个最终类,他实现了很多类的接口。实现类有Temporal, TemporalAdjuster, ChronoLocalDateTime, Serializable。
单一来看,可能看不出来区别,我们将上两篇文章放在一起看,LocalDate、LocalTime、LocalDateTime分别实现的类如下:
● LocalTime
Temporal, TemporalAdjuster, Comparable, Serializable。
● LocalDate
Temporal, TemporalAdjuster, ChronoLocalDate, Serializable。
● LocalDateTime
Temporal, TemporalAdjuster, ChronoLocalDateTime, Serializable。
从中我们看出来,Temporal, TemporalAdjuster,Serializable是共同实现的接口,我们只需要将不同点讲清楚就可以了。
LocalDateTime在创建日期的时候可以说包含了LocalTime和LocalDate,其中囊括的有年、月、日、时、分、秒、毫秒。
测试代码如下:
当前日期,衍生出来两个方法,其中一个是从时区获取当前日期,另外一个是从从时钟方式获取
public static void main(String[] args) {
System.out.println("-- LocalDateTime自带API功能");
//
System.out.println("LocalDateTime.now() = " + LocalDateTime.now());
//
System.out.println("LocalDateTime.now(ZoneId.of('Asia/Shanghai')) = " + LocalDateTime.now(ZoneId.of("Asia/Shanghai")));
System.out.println("LocalDateTime.now(Clock.systemDefaultZone()) = " + LocalDateTime.now(Clock.systemDefaultZone()));
}
测试结果如下:
-- LocalDateTime自带API功能
LocalDateTime.now() = 2023-12-30T17:07:43.519
LocalDateTime.now(ZoneId.of('Asia/Shanghai')) = 2023-12-30T17:07:43.519
LocalDateTime.now(Clock.systemDefaultZone()) = 2023-12-30T17:07:43.519
在LocalDateTime类中,有如下几个方法,都是根据不同条件来创建一个时间。
测试代码如下:
(1)of函数,基础的设定,此处只举例一个
(2)of函数,获取一个设定日期,此方法感觉是一个欠揍的方法,但是作为API又不得不存在,他是集成了LocalDate、LocalTime。
(3)ofXXX函数
public static void main(String[] args) {
//
System.out.println("LocalDateTime.of(2023, 12, 30, 18,26, 34 ) = " + LocalDateTime.of(2023, 12, 30, 18,26, 34 ));
//
System.out.println("LocalDateTime.of(LocalDate.now(), LocalTime.now() = " + LocalDateTime.of(LocalDate.now(), LocalTime.now()));
//
System.out.println("LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()) = " + LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()));
}
测试结果如下:
LocalDateTime of(LocalDate date, LocalTime time)获取一个设定日期,此方法感觉是一个欠揍的方法,但是作为API又不得不存在,他是集成了LocalDate和LocalTime。所以提前学习好这里函数,到了LocalDateTime这里就比较好好操作,熟练后就是闭着眼睛也能写出可以跑的代码。
时间转换,同其他函数一样,这里有两个构造,此处只演示一个案例,另外一个还希望多操作实践下。
测试代码如下:
// 转换时间
System.out.println("LocalDateTime.parse(\"2023-12-30T18:26:34\") = " + LocalDateTime.parse("2023-12-30T18:26:34"));
测试结果如下:
LocalDateTime.parse("2023-12-30T18:26:34") = 2023-12-30T18:26:34
注意??:如果你看过前面的文章,可能会发现,在LocalDateTime类中没有提及LocalDate 类中的ofYearDay()方法,也没有提及到LocalTime 类中ofNanoOfDay()方法和ofSecondOfDay()方法。如果你知道答案,还望能在评论区说说你的想法。
在LocalDateTime中如同LocalDate和LocalTime一样,也有很多继承和重写的方法。
这里获取的字段其实就是我们在上面的年、月、日、时、分、秒、毫秒、纳秒以及一些常用的本年第几日、本月底几日、本周第几日等。
getDayOfXXX函数,获取当前日期的星期(英文)、当前日期所在月份中的第几天、当前日期所在年份中的第几天。
//
System.out.println("LocalDateTime.now().getDayOfWeek() = " + LocalDateTime.now().getDayOfWeek());
System.out.println("LocalDateTime.now().getDayOfMonth() = " + LocalDateTime.now().getDayOfMonth());
System.out.println("LocalDateTime.now().getDayOfYear() = " + LocalDateTime.now().getDayOfYear());
测试打印结果:
LocalDateTime.now().getDayOfWeek() = SATURDAY
LocalDateTime.now().getDayOfMonth() = 30
LocalDateTime.now().getDayOfYear() = 364
LocalDateTime中的withXXX方法涵盖了LocalDate和LocalTime中的withXXX方法。
测试代码如下:
(1)返回当前月、周、年的星期几。例如返回当前月的第一天、返回本周的星期二、星期三的时间。
(2)主要是月份的设置,例如设置10月份,当前时间的10号,当前时间的6点,那么就返回当前日期的副本且只修改数据。
(3)主要是月份的设置,例如设置10月份,当前时间的10号,当前时间的6点,那么就返回当前日期的副本且只修改数据。
// withXXX函数
//
System.out.println("LocalDateTime.now().with(LocalDate.now())) = " + LocalDateTime.now().with(LocalDate.now()));
System.out.println("LocalDateTime.now().with(ChronoField.DAY_OF_MONTH, 1)) = " + LocalDateTime.now().with(ChronoField.DAY_OF_MONTH, 1));
System.out.println("LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 2) = " + LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 2));
System.out.println("LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 3) = " + LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 3));
//
System.out.println("LocalDateTime.now().withMonth(10) = " + LocalDateTime.now().withMonth(10));
System.out.println("LocalDateTime.now().withDayOfMonth(10)) = " + LocalDateTime.now().withDayOfMonth(10));
System.out.println("LocalDateTime.now().withHour(6)) = " + LocalDateTime.now().withHour(6));
测试结果如下:
LocalDateTime.now().with(LocalDate.now())) = 2023-12-30T18:06:51.464
LocalDateTime.now().with(ChronoField.DAY_OF_MONTH, 1)) = 2023-12-01T18:06:51.464
LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 2) = 2023-12-26T18:06:51.464
LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 3) = 2023-12-27T18:06:51.465
LocalDateTime.now().withMonth(10) = 2023-10-30T18:06:51.465
LocalDateTime.now().withDayOfMonth(10)) = 2023-12-10T18:06:51.465
LocalDateTime.now().withHour(6)) = 2023-12-30T06:06:51.465
LocalDateTime中的判断方法主要有
● 在某个之前
● 在某个时间之后
● 是否等于
● 是否在有效范围内/JDK设定的范围是否符合
咿呀,感觉是否又少了一个判断是否是闰年?哦,这个只在LocalDate中存在,在LocalDateTime和LocalTime并不存在。此时,我们从另外一个方面看待这个问题,其实就比较好理解了。
闰年,只是在日期中存在,在时间这个概念上面不存在;LocalDateTime兼容的度最小颗粒是时间,所以LocalDateTime和LocalTime是时间类,而LocalDate是日期类。所以在LocalDateTime中是没有闰年的判断的。有些时间我们也常常说,LocalDateTime为长时间,而LocalTime短时间也是这个道理。
在LocalDateTime中,加法和减法是相互呼应的。可以参考表情的方法或者JDK中的方法进行参数设定,即可以使用。
测试代码如下:
(1)日期加减,主要有两种类型:第一种是直接进行加减、使用TemporalAmount参数设定;第二种就是直接设定具体的参数。
(2)方式一 在当前日期增加3个周期,周期单位为天
(3)方式二 在当前日期增加4天,在当前日期减少2周
//
// 方式一
System.out.println("LocalDateTime.now().plus(Period.ofDays(3)) = " + LocalDateTime.now().plus(Period.ofDays(3)));
// 方式二
System.out.println("LocalDateTime.now().plusDays(3) = " + LocalDateTime.now().plusDays(4));
System.out.println("LocalDateTime.now().minusWeeks(2) = " + LocalDateTime.now().minusWeeks(2));
测试结果如下:
LocalDateTime.now().plus(Period.ofDays(3)) = 2024-01-02T18:06:51.466
LocalDateTime.now().plusDays(3) = 2024-01-03T18:06:51.466
LocalDateTime.now().minusWeeks(2) = 2023-12-16T18:06:51.466
在JDK8之前我们都是使用Date或者Calendar来做计算或者转换,自从有了JDK8,我们的CVX速度很明显增强了。JDK8引入了许多新的特性和改进,使得代码编写更加简洁、可读性更高,并且提供了更好的性能和并发处理能力。
欢迎关注博主 「六月暴雪飞梨花」 或加入【六月暴雪飞梨花社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。