一.JDK8新特性之日期时间API-案例实操
之前我们学习了Stream流、Lambda表达式以及方法引用等相关的内容,如果想学习的同学可以看一下之前的文章,接下来我们一起学习一下关于JDK8中新日期时间API的使用。
二.JDK中原始日期时间存在的问题
- 设计不合理,没有一个统一衡量的标准,在java.util和java.sql的包各自中都有日期类。
- 非线程安全,所有的日期类都是可变的。
- 不提供时区支持。
三. JDK8新特性之新日期时间API
JDK 8中全新的日期时间API,是线程安全的。新的日期及时间API位于 java.time 包中,以下是关于日期时间关键类API。
- LocalDate :表示日期,包含年月日,格式为 2019-10-16
- LocalTime :表示时间,包含时分秒,格式为 16:38:54.158549300
- LocalDateTime :表示日期时间,包含年月日,时分秒,格式为 2018-09-06T15:33:56.750
- DateTimeFormatter :日期时间格式化类。
- Instant:时间戳,表示一个特定的时间瞬间。
- Duration:用于计算2个时间(LocalTime,时分秒)的距离
- Period:用于计算2个日期(LocalDate,年月日)的距离
- ZonedDateTime :包含时区的时间
Java中使用的历法是ISO 8601日历系统,它是世界民用历法,也就是我们所说的公历。平年有365天,闰年是366
天。此外Java 8还提供了4套其他历法,分别是:
- ThaiBuddhistDate:泰国佛教历
- MinguoDate:中华民国历
- JapaneseDate:日本历
- HijrahDate:伊斯兰历
3.1 日期时间的常见操作以及案例实操
3.1.1 LocalDate创建指定的日期
案例代码
import java.time.LocalDate;
public class Demo {
public static void main(String[] args) {
// 创建指定的日期
LocalDate date = LocalDate.of(2023, 2, 26);
System.out.println("创建指定的日期为 "+date);
// 得到当前的日期
LocalDate now = LocalDate.now();
System.out.println("当前的时间为 "+now);
// 根据LocalDate对象获取对应的日期信息
System.out.println("年:" + now.getYear());
System.out.println("月:" + now.getMonth().getValue());
System.out.println("日:" + now.getDayOfMonth());
System.out.println("星期:" + now.getDayOfWeek().getValue());
}
}
结果展示:
3.1.2 LocalTime创建指定的时间
案例代码
import java.time.LocalTime;
public class Demo {
public static void main(String[] args) {
// 指定的时间
LocalTime time = LocalTime.of(6,6,6,666);
System.out.println("设置指定的时间为"+time);
// 获取当前的时间
LocalTime nowtime = LocalTime.now();
System.out.println("获取当前的时间"+nowtime);
// 获取时间信息:小时、分钟、秒、纳秒等相关的信息
System.out.println(nowtime.getHour());
System.out.println(nowtime.getMinute());
System.out.println(nowtime.getSecond());
System.out.println(nowtime.getNano());
}
}
运行结果
3.1.1 LocalDateTime创建指定的日期和时间
就是之前日期类和时间类的增强版本
案例代码
import java.time.LocalDateTime;
public class Demo {
public static void main(String[] args) {
// 设置指定的日期时间
LocalDateTime dateTime = LocalDateTime.of(2023
, 9
, 01
, 9
, 10
, 10
, 910);
System.out.println("设置指定日期的时间为:"+dateTime);
// 获取当前的日期时间
LocalDateTime nowTime = LocalDateTime.now();
System.out.println("获取当前的日期时间:"+nowTime);
// 获取日期时间信息
System.out.println(nowTime.getYear());
System.out.println(nowTime.getMonth().getValue());
System.out.println(nowTime.getDayOfMonth());
System.out.println(nowTime.getDayOfWeek().getValue());
System.out.println(nowTime.getHour());
System.out.println(nowTime.getMinute());
System.out.println(nowTime.getSecond());
System.out.println(nowTime.getNano());
}
}
运行结果
3.2 日期时间的修改和比较
3.2.1 原来的时间上设置新时间,并不会修改原来时间的相关信息
修改日期时间 对日期时间的修改,对已存在的LocalDate对象,新创建了对象,相当于拷贝了原来的时间对象,它并不会修改原来的信息。
案例代码
import java.time.LocalDateTime;
public class Demo {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("现在的时间: "+now);
// 设置时间为1998 注意:此时获得是另一个对象相关的时间,原来的时间并没有改变
LocalDateTime localDateTime = now.withYear(1998);
System.out.println("还是现在的时间,并没有改变:"+now);
System.out.println("修改后的时间" + localDateTime);
}
}
结果展示:
3.2.2 日期时间的设置与修改
案例代码
import java.time.LocalDateTime;
public class Demo {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("现在的时间: "+now);
// 设置时间为1998 注意:此时获得是另一个对象相关的时间,原来的时间并没有改变
LocalDateTime localDateTime = now.withYear(2001);
System.out.println("还是现在的时间,并没有改变:"+now);
System.out.println("修改后的时间" + localDateTime);
// 在当前日期时间的基础上 加上或者减去指定的时间
System.out.println("5年后:"+now.plusYears(5));
System.out.println("5月后:"+now.plusMonths(5));
System.out.println("5天后:"+now.plusDays(5));
System.out.println("5年前:"+now.minusYears(5));
System.out.println("5月前:"+now.minusMonths(5));
System.out.println("5天前:"+now.minusDays(5));
}
}
运行结果
3.2.3 日期时间的比较
在JDK8中日期的比较的相关API方法:isAfter 、isBefore、 isEqual
实现案例
import java.time.LocalDateTime;
public class Demo {
public static void main(String[] args) {
LocalDateTime before = LocalDateTime.of(2022,2,3,5,4,2,123);
LocalDateTime now = LocalDateTime.now();
System.out.println(now.isAfter(before));
System.out.println(now.isBefore(before));
System.out.println(now.isEqual(before));
}
}
运行结果
3.3 格式化和解析操作
在JDK8中我们可以通过java.time.format.DateTimeFormatter
类可以进行日期的解析和格式化操作
案例代码
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Demo {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
// DateTimeFormatters时间格式化类来指定时间被格式化的格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format = now.format(dateTimeFormatter);
System.out.println("格式化后的时间为:" + format);
}
}
运行结果
3.4 Instant类
在JDK8中给我们新增一个Instant类(时间戳/时间线),内部保存了从1970年1月1日 00:00:00以来的秒和纳秒
案例如下:
import java.time.Instant;
public class Demo {
public static void main(String[] args) throws InterruptedException {
// 获取从1970年一月一日 00:00:00 到现在的 纳秒
System.out.println(Instant.now().getNano());
}
}
结果展示
3.5 计算日期时间差
3.5.1 Period:用来计算两个日期差(LocalDate)
案例代码
import java.time.LocalDate;
import java.time.Period;
public class Demo {
public static void main(String[] args) throws InterruptedException {
// 计算日期差
LocalDate nowDate = LocalDate.now();
LocalDate date = LocalDate.of(2020, 2, 5);
Period period = Period.between(date, nowDate);
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
}
}
结果展示:
3.5.2 Duration:用来计算两个时间差(LocalTime)
案例代码如下:
import java.time.Duration;
import java.time.LocalTime;
public class Demo {
public static void main(String[] args) throws InterruptedException {
// 计算时间差
LocalTime now = LocalTime.now();
LocalTime time = LocalTime.of(18, 2, 14);
// 通过Duration来计算时间差
Duration duration = Duration.between(now, time);
System.out.println(duration.toDays());
System.out.println(duration.toHours());
System.out.println(duration.toMinutes());
System.out.println(duration.toMillis());
}
}
结果展示:
3.6 时间校正器(时钟)
有时候我们想要时间校正器设置为这个月第几周的第几天,获取其它的日期,我们可以设置时间和日期。这时我们通过时间校正器效果会更好。
3.6.1 TemporalAdjuster:自定义时间校正器
案例代码
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjuster;
public class Demo {
public static void main(String[] args) throws InterruptedException {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
// 将当前的日期调整到4个月后的第5天
TemporalAdjuster adJuster = (temporal)->{
LocalDateTime dateTime = (LocalDateTime) temporal;
LocalDateTime nextTime = dateTime.plusMonths(4).withDayOfMonth(5);
return nextTime;
};
LocalDateTime nextTime = now.with(adJuster);
System.out.println(nextTime);
}
}
结果展示:
3.6.2 TemporalAdjusters:通过该类静态方法提供了大量的常用TemporalAdjuster的实现。
TemporalAdjusters提供了许多的方法
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
public class Demo {
public static void main(String[] args){
LocalDateTime now = LocalDateTime.now();
LocalDateTime nextMonth = now.with(TemporalAdjusters.firstDayOfYear());
System.out.println("设置为该年的第一天 " + nextMonth);
}
}
结果展示
3.7 日期时间的时区
3.7.1 基本知识
Java8 中加入了对时区的支持,LocalDate、LocalTime、LocalDateTime是不带时区的,带时区的日期时间类分别为:ZonedDate、ZonedTime、ZonedDateTime。
其中每个时区都对应着 ID,ID的格式为 “区域/城市” 。例如 :Asia/Shanghai 等。
ZoneId:该类中包含了所有的时区信息
3.7.2 获取所有时区的id
案例代码
public class Demo {
public static void main(String[] args){
// 获取所有的时区id
ZoneId.getAvailableZoneIds().forEach(System.out::println);
}
}
结果展示:
3.7.3 获取指定时区
案例代码
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Demo {
public static void main(String[] args){
// 获取标准时间
ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());
System.out.println("now1 = " + now1);
// 获取中国使用的东八区的时区,比标准时间早8个小时
LocalDateTime now2 = LocalDateTime.now();
System.out.println("now2 = " + now2);
// 使用计算机默认的时区,创建日期时间
ZonedDateTime now3 = ZonedDateTime.now();
System.out.println("now3 = " + now3);
// 使用指定的时区创建日期时间
ZonedDateTime now4 = ZonedDateTime.now(ZoneId.of("Australia/Tasmania"));
System.out.println("now4 = " + now4);
}
}
结果展示
四.JDK8新特性之日期时间API优势:
- 新版日期时间API中,日期和时间对象是不可变,操作日期不会影响原来的值,而是生成一个新的实例。
- 提供不同的两种方式,有效的区分了人和机器的操作。
- TemporalAdjuster可以更精确的操作日期,还可以自定义日期调整期。
- 解决了之前日期时间线程不安全的问题。在进行日期时间修改的时候,原来的LocalDate对象是不会被修改,每次操作都是返回了一个新的LocalDate对象,所以在多线程场景下是数据安全的。
五.勉励
又是劳累的一天啊,坚持,坚持,坚持!
一定要听父母的话,多锻炼,多锻炼,好了,不多了,出去跑会儿步,加油。
我是硕风和炜,我们下篇文章见。