点击上方蓝色“Java十年君”,选择“设为星标”。
一、为什么要使用新日期时间
Java8之前的标准日期和时间存在以下缺陷:
- Date 可读性差 示例:Sat Nov 28 11:40:51 CST 2020
- SimpleDateFormat 是线程不安全的,多线程并发处理时会得到意想不到的结果
- Date 对日期的计算等操作处理比较繁琐,不够简洁
为解决上述缺陷,出现一些优秀三方日期处理框架,Joda-Time等。Joda-Time在Java 8之前成为Java的实际标准日期和时间库。
Java需要一套新的标准的日期时间API,于是在Java 8中引入的java.time包,遵守JSR310规范。
值得一提的是,Joda-Time的作者和Oracle一起共同参与了这些API的设计和实现。
二、新日期时间类
1、LocalDate: 当前日期,包含年月日,格式:yyyy-MM-dd
// 初始化
LocalDate nowLocalDate = LocalDate.now();
LocalDate localDate = LocalDate.of(2020,11,15);
LocalDate localDate = LocalDate.of(2020, Month.NOVEMBER,1);
// 获取当月中的天数
localDate.getDayOfMonth();
// 获取当年中的天数
localDate.getDayOfYear();
// 获取周中的天数
localDate.getDayOfWeek().getValue();
// 获取月份
localDate.getMonthValue();
2、LocalTime: 当前时间,包含时分秒,格式:HH:mm:ss
// 初始化
LocalTime localTime = LocalTime.now();
LocalTime localTime = LocalTime.of(12,10,20);
// 获取小时
localTime.getHour();
// 获取分钟
localTime.getMinute();
// 获取秒
localTime.getSecond();
// 获取纳秒
localTime.getNano();
3、LocalDateTime: 当前日期+时间 格式:yyyy-MM-dd'T'HH:mm:ss
// 当前日期+时间 yyyy-MM-dd'T'HH:mm:ss
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime localDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.now());
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 17, 20, 10, 9);
localDateTime.getDayOfMonth();
localDateTime.getDayOfYear();
4、Instant: 时间戳,精确到纳秒(Nano-Second),与我们常使用的System.currentTimeMillis()有些类似,System.currentTimeMillis()方法只精确到毫秒(Milli-Second)
Instant instant = Instant.now();
Instant instant = Instant.ofEpochSecond(1000L);
instant.getEpochSecond();
instant.toEpochMilli();
instant.getNano();
5、ZonedDateTime:特定时区的日期和时间
格式示例:2020-11-28T11:52:20.200+08:00[Asia/Shanghai]
ZonedDateTime zonedDateTime = ZonedDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault());
ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.systemDefault());
ZonedDateTime zonedDateTime = ZonedDateTime.of(2020, 11, 16, 1, 1, 0, 0, ZoneId.systemDefault());
6、ZoneId:时区
// 当前系统默认时区
ZoneId zoneId = ZoneId.systemDefault();
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
// 查询全部可用时区
Set zoneIds = ZoneId.getAvailableZoneIds();
7、DateTimeFormatter:日期时间格式化
// 格式化
// yyyyMMdd
String dateStr1 = LocalDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE);
//yyyy-MM-dd
String dateStr2 = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
// yyyy-MM-dd'T'HH:mm:ss
String dateStr3 = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
// HH:mm:ss
String dateStr4 = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_TIME);
// 自定义格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateStr = LocalDateTime.now().format(dateTimeFormatter);
// 解析
LocalDateTime parseDate = LocalDateTime.parse("2020-11-28 11:11:22",dateTimeFormatter);
8、Duration:间隔,时间段
// 时间间隔
Duration duration = Duration.between(LocalDateTime.of(2020,11,15, 21,0,0),
LocalDateTime.of(2020,11,16,1,1,0));
duration.getSeconds();
duration.toDays();
duration.toHours();
duration.getNano();
duration.toMinutes();
duration.toMillis();
duration.toNanos();
9、Period 间隔,时间段,仅支持年、月、日
区别:Period基于日期值,而Duration基于时间值
Period period = Period.between(LocalDate.now(), LocalDate.of(2020, 11, 16));
period.getYears();
period.getMonths();
period.getDays();
10、日期比较
// 判断是否在指定日期之后
localDateTime.isAfter(LocalDateTime.now());
// 判断是否在指定日期之前
localDateTime.isBefore(LocalDateTime.now());
// 判断是否和指定日期相等
localDateTime.isEqual(LocalDateTime.now());
// 和指定日期比较,负数是小,0 时等于 ,正数是大
localDateTime.compareTo(LocalDateTime.now());
11、日期操作:增加,减小,修改
// 减小
localDateTime.minusYears(1L);
localDateTime.minusMonths(1L);
localDateTime.minusWeeks(1L);
localDateTime.minusDays(1L);
localDateTime.minusHours(1L);
localDateTime.minusMinutes(1L);
localDateTime.minusSeconds(1L);
localDateTime.minusNanos(1L);
// 增加
localDateTime.plusYears(1L);
localDateTime.plusMonths(1L);
localDateTime.plusWeeks(1L);
localDateTime.plusDays(1L);
localDateTime.plusHours(1L);
localDateTime.plusMinutes(1L);
localDateTime.plusSeconds(1L);
localDateTime.plusNanos(1L);
// 修改
LocalDateTime localDateTime = LocalDateTime.now();
localDateTime = localDateTime.withYear(2019);
localDateTime = localDateTime.withMonth(1);
localDateTime = localDateTime.withDayOfMonth(1);
localDateTime = localDateTime.withDayOfYear(1);
localDateTime = localDateTime.withHour(1);
localDateTime = localDateTime.withMinute(1);
localDateTime = localDateTime.withSecond(30);
12、更复杂的时间操作,使用TemporalAdjuster
TemporalAdjuster是函数接口,调整Temporal对象的策略,在TemporalAdjusters中有预定义的实现,同时也可自定义实现。
使用示例:
//获取下个月的第一天
LocalDateTime firstDayOfNextMonth = LocalDateTime.now().with(TemporalAdjusters.firstDayOfNextMonth());
预定义实现:
// 当月第一天
TemporalAdjusters.firstDayOfMonth();
// 下月第一天
TemporalAdjusters.firstDayOfNextMonth();
// 当年第一天
TemporalAdjusters.firstDayOfYear();
// 下年的第一天
TemporalAdjusters.firstDayOfNextYear();
// 当月的最后一天
TemporalAdjusters.lastDayOfMonth();
// 当年的最后一天
TemporalAdjusters.lastDayOfYear();
// 当月的最后一个星期几
TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY);
// 当月的最开始一个星期几
TemporalAdjusters.firstInMonth(DayOfWeek.FRIDAY);
// 后一个星期几
TemporalAdjusters.next(DayOfWeek.MONDAY);
// 前一个星期几
TemporalAdjusters.previous(DayOfWeek.MONDAY);
// 返回后一个给定的星期几,如果这个值满足条件,直接返回
TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY);
// 返回前一个给定的星期几,如果这个值满足条件,直接返回
TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY);
// 返回同一个月中每周的第几天
TemporalAdjusters.dayOfWeekInMonth(1,DayOfWeek.MONDAY);
自定义实现:
//自定义,14天后的日期
LocalDateTime.now().with(temporal -> {
return temporal.plus(14, ChronoUnit.DAYS);
});
三、时间类之间的关系和相互转换
![1892f1c5b1ed9eeb93f23bf970812560.png](https://i-blog.csdnimg.cn/blog_migrate/cb7898eea19a5a5ed7a75b0fe4058b86.png)
转换关系:
// localDate + localTime <=> localDateTime
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.of(localDate,localTime);
// LocalDateTime + ZoneId <=> ZonedDateTime
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime,zoneId);
// Instant+ ZoneId <=> ZonedDateTime
Instant instant = zonedDateTime.toInstant();
ZonedDateTime zonedDateTime = instant.atZone(zoneId);
// Date <=> Instant
Date date = Date.from(instant);
Instant instant = date.toInstant();
//LocalDateTime -> Date
Date date = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());
// Date -> LocalDateTime
LocalDateTime localDateTime=(new Date()).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
四、小结
JAVA8提供的日期时间对象是不可变对象。日期操作会返回一个新的实例,老的日期时间对象不会发生改变。
支持精细化的操作日期和时间。
新日期时间类之间转换更加简洁,清晰。
快来一起使用新的日期时间API,优雅的处理时间。
![e0c2ccaf21df650be39962d673a6c2f4.png](https://i-blog.csdnimg.cn/blog_migrate/db80ceb02df8ec4255bfada48469e117.jpeg)