一、旧时间日期问题
-
在 java.util 和 java.sql 包下都有时间日期类
-
java.util.Date 类包含时间和日期
-
java.sql.Date 类值包含日期
-
-
java.util.Date 类线程不安全,Date 对象可变
-
时间日期格式化类在 java.text 包下
-
时区处理困难,并不支持国际化,没有时区支持
java
package com.my.olddate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class OldDateTest {
public static void main(String[] args) {
// 设计不合理
Date date = new Date(2022, 7, 30);
System.out.println(date); // Wed Aug 30 00:00:00 CST 3922
System.out.println("--------------------");
// 存在线程安全问题
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
for (int i = 0; i < 50; i++) {
new Thread(() -> {
try {
System.out.println(simpleDateFormat.parse("2022-07-30"));
} catch (ParseException e) {
e.printStackTrace();
}
}).start();
}
}
}
二、新时间日期概述
1、基本介绍
-
JDK 8 增加了一套全新的时间日期 API,这套 API 设计合理,线程安全
-
新时间日期 API 位于 java.time 包下
2、关键类介绍
类 | 说明 |
---|---|
LocalDate | 日期,年月日 |
LocalTime | 时间,时分秒 |
LocalDateTime | 日期时间,年月日时分秒 |
DateTimeFormatter | 日期时间格式化类 |
Instant | 时间戳,时间瞬间 |
Duration | 计算时间差 |
Period | 计算日期差 |
ZonedDateTime | 包含时区的时间 |
- Java 中使用的是 ISO 8601 日期和时间的表示方法,是世界民用历法,即公历,平年有 365 天,闰年有 366 天
三、新时间日期操作
1、新时间日期创建
- 创建指定日期
java
LocalDate date1 = LocalDate.of(2022, 6, 30);
System.out.println(date1);
- 创建当前日期
java
LocalDate date2 = LocalDate.now();
System.out.println(date2);
- 创建指定时间
java
LocalTime time1 = LocalTime.of(15, 30, 30, 123);
System.out.println(time1);
- 创建当前时间
java
LocalTime time2 = LocalTime.now();
System.out.println(time2);
- 创建指定日期时间
java
LocalDateTime localDateTime1 = LocalDateTime.of(2022, 6, 30, 15, 30, 30, 123);
System.out.println(localDateTime1);
- 创建当前日期时间
java
LocalDateTime localDateTime2 = LocalDateTime.now();
System.out.println(localDateTime2);
2、新时间日期信息获取
- LocalDate 对象信息获取
java
LocalDate localDate = LocalDate.now();
System.out.println("年:" + localDate.getDayOfYear());
System.out.println("月:" + localDate.getMonth().getValue() + " " + localDate.getMonth());
System.out.println("日:" + localDate.getDayOfMonth());
System.out.println("星期:" + localDate.getDayOfWeek().getValue() + " " + localDate.getDayOfWeek());
- LocalTime 对象信息获取
java
LocalTime localTime = LocalTime.now();
System.out.println("时:" + localTime.getHour());
System.out.println("分:" + localTime.getMinute());
System.out.println("秒:" + localTime.getSecond());
System.out.println("纳秒:" + localTime.getNano());
- LocalDateTime 对象信息获取
java
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("年:" + localDateTime.getDayOfYear());
System.out.println("月:" + localDateTime.getMonth().getValue() + " " + localDateTime.getMonth());
System.out.println("日:" + localDateTime.getDayOfMonth());
System.out.println("星期:" + localDateTime.getDayOfWeek().getValue() + " " + localDateTime.getDayOfWeek());
System.out.println("时:" + localDateTime.getHour());
System.out.println("分:" + localDateTime.getMinute());
System.out.println("秒:" + localDateTime.getSecond());
System.out.println("纳秒" + localDateTime.getNano());
3、新时间日期修改
- 通过设置时间日期进行修改
java
LocalDateTime now = LocalDateTime.now();
System.out.println("当前日期时间:" + now);
System.out.println("修改年:" + now.withYear(2000));
System.out.println("修改月:" + now.withMonth(10));
System.out.println("修改日:" + now.withDayOfMonth(25));
System.out.println("修改时:" + now.withHour(20));
System.out.println("修改分:" + now.withMinute(10));
System.out.println("修改秒:" + now.withSecond(30));
System.out.println("修改纳秒:" + now.withNano(123456));
- 通过加减时间日期进行修改
java
LocalDateTime now = LocalDateTime.now();
System.out.println("五年后:" + now.plusYears(5));
System.out.println("五个月后:" + now.plusMonths(5));
System.out.println("五天后:" + now.plusDays(5));
System.out.println("五小时后:" + now.plusHours(5));
System.out.println("五分钟后:" + now.plusMinutes(5));
System.out.println("五秒后:" + now.plusSeconds(5));
System.out.println("五纳秒后:" + now.plusNanos(5));
System.out.println("--------------------");
System.out.println("五年前:" + now.minusYears(5));
System.out.println("五个月前:" + now.minusMonths(5));
System.out.println("五天前:" + now.minusDays(5));
System.out.println("五小时前:" + now.minusHours(5));
System.out.println("五分钟前:" + now.minusMinutes(5));
System.out.println("五秒前:" + now.minusSeconds(5));
System.out.println("五纳秒前:" + now.minusNanos(5));
4、新时间日期线程安全问题
- 新时间日期类每次修改都会创建新的对象,原来的对象是不会被修改的,不会存在线程安去问题
java
package com.my.newdate;
import java.time.LocalDateTime;
public class NewDateSafeTest {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime localDateTime = now.plusYears(5);
System.out.println(now + " " + now.hashCode());
System.out.println(localDateTime + " " + localDateTime.hashCode());
}
}
5、新时间日期比较
java
package com.my.newdate;
import java.time.LocalDateTime;
public class NewDateCompareTest {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 1, 15, 30, 30);
System.out.println(now.isAfter(localDateTime));
System.out.println(now.isBefore(localDateTime));
System.out.println(now.isEqual(localDateTime));
}
}
四、新时间日期格式化与解析
- 使用 java.time.format.DateTimeFormatter 进行格式化和解析操作
1、新时间日期格式化
- 使用系统默认格式进行格式化
java
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter basicIsoDate = DateTimeFormatter.BASIC_ISO_DATE;
String format = now.format(basicIsoDate);
System.out.println(format);
- 使用指定格式进行格式化
java
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format = now.format(dateTimeFormatter);
System.out.println(format);
2、新时间日期解析
java
package com.my.newdate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class NewDateParseTest {
public static void main(String[] args) {
String str2 = "2022-07-30 17:36:44";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime2 = LocalDateTime.parse(str2, dateTimeFormatter);
System.out.println(localDateTime2);
}
}
五、时间戳
1、基本介绍
- Instant 类,时间戳,可以获取从 1970-01-01 00:00:00 起的秒数
2、基本使用
- 获取时间戳
java
Instant now = Instant.now();
System.out.println(now);
- 获取秒数
java
Instant now = Instant.now();
System.out.println(now.getEpochSecond());
- 获取纳秒数
java
Instant now = Instant.now();
System.out.println(now.toEpochMilli());
- 通过秒数获取时间戳
java
Instant instant = Instant.ofEpochSecond(1659176030L);
System.out.println(instant);
- 通过纳秒数获取时间戳
java
Instant instant2 = Instant.ofEpochMilli(1659176030725L);
System.out.println(instant2);
- 耗时统计
java
Instant start = Instant.now();
Thread.sleep(5);
Instant end = Instant.now();
System.out.println("耗时(纳秒):" + (end.toEpochMilli() - start.toEpochMilli()));
六、计算时间日期差
- Duration 和 Period 类,用来计算时间日期差
1、计算时间差
java
package com.my.newdate;
import java.time.Duration;
import java.time.LocalTime;
public class DurationTest {
public static void main(String[] args) {
LocalTime now = LocalTime.now();
LocalTime time = LocalTime.of(10, 1, 1);
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.toMillis());
System.out.println("纳秒数差:" + duration.toNanos());
}
}
2、计算日期差
java
package com.my.newdate;
import java.time.LocalDate;
import java.time.Period;
public class PeriodTest {
public static void main(String[] args) {
LocalDate now = LocalDate.now();
LocalDate date = LocalDate.of(2020, 1, 1);
Period period = Period.between(date, now);
System.out.println("年份差:" + period.getYears());
System.out.println("月份差:" + period.getMonths());
System.out.println("日份差:" + period.getDays());
}
}
七、时间矫正器
1、TemporalAdjuster
(1)基本介绍
- TemporalAdjuster 是一个函数式接口,adjustInto 方法需要传入一个 Temporal 接口,Temporal 接口的实现类有LocalDate、LocalTime、LocalDateTime 等
java
@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}
(2)基本使用
java
package com.my.newdate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjuster;
public class TemporalAdjusterTest {
public static void main(String[] args) {
// 将当前日期调整为下个月的第一天
LocalDateTime now = LocalDateTime.now();
TemporalAdjuster temporalAdjuster = (temporal) -> {
LocalDateTime localDateTime = (LocalDateTime) temporal;
LocalDateTime nextLocalDateTime = localDateTime.plusMonths(1).withDayOfMonth(1);
return nextLocalDateTime;
};
LocalDateTime nextLocalDateTime = now.with(temporalAdjuster);
System.out.println(nextLocalDateTime);
}
}
2、TemporalAdjusters
(1)基本介绍
- TemporalAdjusterTests 类有大量静态方法提供 TemporalAdjusterTest 接口的实现
(2)基本使用
java
package com.my.newdate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
public class TemporalAdjustersTest {
public static void main(String[] args) {
// 将当前日期调整为明年的第一天
LocalDateTime now = LocalDateTime.now();
LocalDateTime nextLocalDateTime = now.with(TemporalAdjusters.firstDayOfNextYear());
System.out.println(nextLocalDateTime);
}
}
八、时区
1、基本介绍
-
JDK 8 增加了对时区的支持
-
LocalDate、LocalTime 和 LocalDateTime 类是不支持时区的
-
支持时区类:ZonedDate、ZonedTime 和 ZonedDateTime 类
2、基本使用
- 获取所有时区 ID
java
ZoneId.getAvailableZoneIds().forEach(System.out::println);
- 获取标准时间,对比当前时间,我国使用东八区,比标准时间早 8 个小时
java
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
// 获取标准时间
ZonedDateTime zonedDateTime = ZonedDateTime.now(Clock.systemUTC());
System.out.println(zonedDateTime);
- 使用计算机默认时区,获取当前时间
java
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime);
- 获取指定时区的时间
java
ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("America/Bogota"));
System.out.println(zonedDateTime2);