目录
一、旧版日期时间 API 存在的问题
二、新日期时间 API介绍
三、JDK 8的日期和时间类
LocalDate写法
LocalTime写法
LocalDateTime写法
对日期时间的修改,使用withAttribute方法
日期时间的比较
四、JDK 8的时间格式化与解析
五、JDK 8的 Instant 类
六、JDK 8的计算日期时间差类
七、JDK 8的时间校正器
八、JDK 8设置日期时间的时区
小结
一、旧版日期时间 API 存在的问题
- 设计很差: 在java.util和java.sql的包中都有日期类,java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期。此外用于格式化和解析的类在java.text包中定义
- 非线程安全:java.util.Date 是非线程安全的,所有的日期类都是可变的
- 时区处理麻烦:日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类
二、新日期时间 API介绍
JDK 8中增加了一套全新的日期时间API,这套API设计合理,是线程安全的。新的日期及时间API位于 java.time 包中,下面是一些关键类。
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:伊斯兰历
三、JDK 8的日期和时间类
LocalDate、LocalTime、LocalDateTime类的实例是不可变的对象,分别表示使用 ISO-8601 日历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。
LocalDate写法
// LocalDate:获取日期时间的信息。格式为 2024-05-10@Testpublic void test01() {// 创建指定日期LocalDate date = LocalDate.of(2024, 5, 10);System.out.println("date = " + date); // 2024-05-10// 得到当前日期LocalDate nowDate = LocalDate.now();System.out.println("nowDate = " + nowDate); // 2024-05-12// 获取日期信息System.out.println("年: " + nowDate.getYear());System.out.println("月: " + nowDate.getMonthValue());System.out.println("日: " + nowDate.getDayOfMonth());System.out.println("星期: " + nowDate.getDayOfWeek());}
LocalTime写法
// LocalTime类: 获取时间信息。格式为 16:38:54.158549300@Testpublic void test02() {// 得到指定的时间LocalTime time = LocalTime.of(12,15, 28, 129_900_000);System.out.println("time = " + time);// 得到当前时间LocalTime nowTime = LocalTime.now();System.out.println("nowTime = " + nowTime);// 获取时间信息System.out.println("小时: " + nowTime.getHour());System.out.println("分钟: " + nowTime.getMinute());System.out.println("秒: " + nowTime.getSecond());System.out.println("纳秒: " + nowTime.getNano());}
LocalDateTime写法
@Testpublic void test03() {LocalDateTime dateTime = LocalDateTime.of(2024, 5, 12, 14, 25, 20);System.out.println("dateTime = " + dateTime);//2024-05-12T14:25:20// 得到当前日期时间LocalDateTime now = LocalDateTime.now();//2024-05-12T14:25:44.890System.out.println("now = " + now);System.out.println(now.getYear());System.out.println(now.getMonthValue());System.out.println(now.getDayOfMonth());System.out.println(now.getHour());System.out.println(now.getMinute());System.out.println(now.getSecond());System.out.println(now.getNano());}
对日期时间的修改,使用withAttribute方法
对已存在的LocalDate对象,创建它的修改版,最简单的方式是使用withAttribute方法。
withAttribute方法会创建对象的一个副本,并按照需要修改它的属性。以下所有的方法都返回了一个修改属性的对象,他们不会影响原来的对象
// LocalDateTime类: 对日期时间的修改@Testpublic void test05() {LocalDateTime now = LocalDateTime.now();System.out.println("now = " + now);// 修改日期时间LocalDateTime setYear = now.withYear(2049);System.out.println("修改年份: " + setYear);System.out.println("now == setYear: " + (now == setYear));System.out.println("修改月份: " + now.withMonth(6));System.out.println("修改小时: " + now.withHour(9));System.out.println("修改分钟: " + now.withMinute(11));// 再当前对象的基础上加上或减去指定的时间LocalDateTime localDateTime = now.plusDays(5);System.out.println("5天后: " + localDateTime);System.out.println("now == localDateTime: " + (now == localDateTime));System.out.println("10年后: " + now.plusYears(10));System.out.println("20月后: " + now.plusMonths(20));System.out.println("20年前: " + now.minusYears(20));System.out.println("5月前: " + now.minusMonths(5));System.out.println("100天前: " + now.minusDays(100));}
日期时间的比较
// 日期时间的比较@Testpublic void test06() {// 在JDK8中,LocalDate类中使用isBefore()、isAfter()、equals()方法来比较两个日期,可直接进行比较。LocalDate now = LocalDate.now();LocalDate date = LocalDate.of(2018, 8, 8);System.out.println(now.isBefore(date)); // false 当前对象在之前返回true,否则返回falseSystem.out.println(now.isAfter(date)); // true 当前对象在之后返回true,否则返回false}
四、JDK 8的时间格式化与解析
通过 java.time.format.DateTimeFormatter 类可以进行日期时间解析与格式化。
// 日期格式化@Testpublic void test04() {// 得到当前日期时间LocalDateTime now = LocalDateTime.now();DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 将日期时间格式化为字符串String format = now.format(formatter);System.out.println("format = " + format);// 将字符串解析为日期时间LocalDateTime parse = LocalDateTime.parse("2024-05-12 10:12:22", formatter);System.out.println("parse = " + parse);}
五、JDK 8的 Instant 类
Instant 时间戳/时间线,内部保存了从1970年1月1日 00:00:00以来的秒和纳秒。
// 时间戳@Testpublic void test07() {Instant now = Instant.now();System.out.println("当前时间戳 = " + now);// 获取从1970年1月1日 00:00:00的秒System.out.println(now.getNano());System.out.println(now.getEpochSecond());System.out.println(now.toEpochMilli());System.out.println(System.currentTimeMillis());Instant instant = Instant.ofEpochSecond(5);System.out.println(instant);}
六、JDK 8的计算日期时间差类
Duration/Period类: 计算日期时间差。
1. Duration:用于计算2个时间(LocalTime,时分秒)的距离
2. Period:用于计算2个日期(LocalDate,年月日)的距离
// Duration/Period类: 计算日期时间差@Testpublic void test08() {// Duration计算时间的距离LocalTime now = LocalTime.now();LocalTime time = LocalTime.of(14, 15, 20);Duration duration = Duration.between(time, now);System.out.println("相差的天数:" + duration.toDays());System.out.println("相差的小时数:" + duration.toHours());System.out.println("相差的分钟数:" + duration.toMinutes());System.out.println("相差的秒数:" + duration.getSeconds());// Period计算日期的距离LocalDate nowDate = LocalDate.now();LocalDate date = LocalDate.of(1998, 8, 8);// 让后面的时间减去前面的时间Period period = Period.between(date, nowDate);System.out.println("相差的年:" + period.getYears());System.out.println("相差的月:" + period.getMonths());System.out.println("相差的天:" + period.getDays());}
七、JDK 8的时间校正器
需要将日期调整到下月的某一天,通过时间校正器来进行
- TemporalAdjuster : 时间校正器。
- TemporalAdjusters : 该类通过静态方法提供了大量的常用TemporalAdjuster的实现。
// TemporalAdjuster类:自定义调整时间@Testpublic void test09() {LocalDateTime now = LocalDateTime.now();// 得到下一个月的第一天TemporalAdjuster firsWeekDayOfNextMonth = temporal -> {LocalDateTime dateTime = (LocalDateTime) temporal;LocalDateTime nextMonth = dateTime.plusMonths(1).withDayOfMonth(1);System.out.println("nextMonth = " + nextMonth);return nextMonth;};LocalDateTime nextMonth = now.with(firsWeekDayOfNextMonth);System.out.println("nextMonth = " + nextMonth);}
八、JDK 8设置日期时间的时区
Java8 中加入了对时区的支持,LocalDate、LocalTime、LocalDateTime是不带时区的,带时区的日期时间类分别为:ZonedDate、ZonedTime、ZonedDateTime。
// 设置日期时间的时区@Testpublic void test10() {// 1.获取所有的时区ID// ZoneId.getAvailableZoneIds().forEach(System.out::println);// 不带时间,获取计算机的当前时间LocalDateTime now = LocalDateTime.now(); // 中国使用的东八区的时区.比标准时间早8个小时System.out.println("now = " + now);// 2.操作带时区的类// now(Clock.systemUTC()): 创建世界标准时间ZonedDateTime bz = ZonedDateTime.now(Clock.systemUTC());System.out.println("bz = " + bz);// now(): 使用计算机的默认的时区,创建日期时间ZonedDateTime now1 = ZonedDateTime.now();System.out.println("now1 = " + now1); // 2019-10-19T16:19:44.007153500+08:00[Asia/Shanghai]// 使用指定的时区创建日期时间ZonedDateTime now2 = ZonedDateTime.now(ZoneId.of("America/Vancouver"));System.out.println("now2 = " + now2); // 2019-10-19T01:21:44.248794200-07:00[America/Vancouver]}
小结
JDK 8新的日期和时间 API的优势:
1. 新版的日期和时间API中,日期和时间对象是不可变的。操纵的日期不会影响老值,而是新生成一个实例。
2. 新的API提供了两种不同的时间表示方式,有效地区分了人和机器的不同需求。
3. TemporalAdjuster可以更精确的操纵日期,还可以自定义日期调整器。
4. 是线程安全的