文章目录
一、概述
Java原本的java.util.Date和java.util.Calendar类会有老版本计算困难、线程不安全、无使用规范等缺点。JDK1.8推出新的时间处理类,解决了JDK1.7及之前的一些问题。
java.time包参考Joda-time的代码,功能强大,Joda-time能实现的功能,java.time也能实现。
参看:
- https://www.bilibili.com/video/BV1aZ4y1j78G
- https://www.runoob.com/java/java8-datetime-api.html
在学习java.time包下的新的时间处理类的时,第一步肯定是参看他的API
所有类:
枚举和异常:
看到枚举,大概就知道枚举是怎么用的了把~
二、常用类
- Instant:时间轴上的时间戳。多用于类型转换
- Duration:表示秒或者纳秒,适合处理很短的时间间隔,精度高
- period:一段时间的年月日,比如距保险到期还有3年2月22天。
- LocalDate:不可变的日期时间对象,可表示年月日。
- LocalTime:不可变,可表示时分秒
- LocalDateTime:不可变,可表示年月日时分秒
下面就是以LocalDateTime为例,做出一些简单的介绍和使用。
1.LocalDateTime
LocalDateTime由final修饰,不可变类,可表示年月日时分秒。这里以LocalDateTime为例,它的很多的方法,在其他类中使用方法都差不多。
1.1 now()方法
获取实例对象,表示当前时间节点,此方法是获取到电脑本机的时间节点。常用类被final修饰,不能使用new关键字创建实例对象,就提供了此方法获取到实例对象。
// 示例 创建LocalDateTime实例对象
LocalDateTime localDateTime = LocalDateTime.now();
1.2 of()方法
根据给定的参数生成对应的日期/时间对象,可以根据给定的参数生成对应的数据。
// 使用of方法 生成2021-05-01 01:01:01 (LocalDateTime)
LocalDateTime time = LocalDateTime.of(2021,Month.MAY,1,1,1,1);
可以选择传递到年月日时分秒,看给定的参数而定。如果of()
方法里面的最后传递的参数是0,默认不封装。
当使用LocalDateTime的of()封装对象的时候,可以传递LocalDate和LocalTime两个参数,也会封装为LocalDateTime对象。
1.3 plus增加
可增减年月日时分秒等,具体查看API。下列给出一点使用示例:
// 使用of方法 生成2021-05-01 01:01:01 (LocalDateTime)
LocalDateTime localDateTime = LocalDateTime.of(2021,Month.MAY,1,1,1,1);
// plus 1年1月1日,接收新的对象
LocalDateTime plus = localDateTime.plus(Period.of(1, 1, 1));
System.out.println(plus);
之后的plusDays(long days)
就是增加天,plusHours(long hour)
是增加小时,等等。
1.4 minus减少
和plus方法使用方式一样。
// 使用of方法 生成2021-05-01 01:01:01 (LocalDateTime)
LocalDateTime localDateTime = LocalDateTime.of(2021,Month.MAY,1,1,1,1);
// minus 1年1月1日,接收新的对象
LocalDateTime minus = localDateTime.minus(Period.of(1, 1, 1));
System.out.println(minus);
1.5 with修改
with可实现 修改日期中的某一个值,比如修改年、月、日等信息(注意,这里不是修改已经存在的类对象,而是创建一个新的类对象)
// 使用of方法 生成2021-05-01 01:01:01 (LocalDateTime)
LocalDateTime localDateTime = LocalDateTime.of(2021,Month.MAY,1,1,1,1);
// with 修改小时为 2
LocalDateTime with = localDateTime.with(ChronoField.HOUR_OF_DAY, 2);
System.out.println(with);
with()配合TemporalAdjusters使用,可实现一些高级的操作,比如:
TemporalAdjusters是一个接口,传递进入with()的是一个TemporalAdjusters的实习类对象。
// 使用of方法 生成2021-05-01 01:01:01 (LocalDateTime)
LocalDateTime localDateTime = LocalDateTime.of(2021,Month.MAY,1,1,1,1);
// with 使用TemporalAdjusters修改为一年的最后一天
LocalDateTime with = localDateTime.with(TemporalAdjusters.lastDayOfYear());
System.out.println(with);
这是with()
的用法,当然还有withMonth()
等方法。
2.ZoneId和ZonedDateTime
ZoneId是时区集合,可以获取到时区的信息,ZonedDateTime是带有时区的LocalDateTime。
// 获取到ZoneId中的时区集合,Jdk收集了600个时区
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
availableZoneIds.stream().forEach(System.out::println);
// 获取到带有时区的ZonedDateTime
ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.of(2021,Month.JULY,1,1,1,1),ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime);
两者配合使用,用于处理时区的相关信息。
设置时区,获取到其他时区的时间:
// 构建LocalDateTime对象
LocalDateTime localDate = LocalDateTime.of(2021,Month.APRIL,1,1,1,1);
// 添加时区信息
ZonedDateTime Shanghai = localDate.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(Shanghai);
// 获取其他时区的时间
ZonedDateTime Tokyo = Shanghai.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
System.out.println(Tokyo);
输出:
2021-04-01T01:01:01+08:00[Asia/Shanghai]
2021-04-01T02:01:01+09:00[Asia/Tokyo]
三、实例超实用
不明白的即使查看官方API哦!
1.java.util.Date和java.time.LocalDateTime的转换
java.util.Date 》java.time.LocalDateTime
借助java.util.Date的toInstant()方法
// 1.初始化Date对象
Date date = new Date();
// 2.获取date的instant对象
Instant instant = date.toInstant();
// 3.填充时区 获取ZonedDateTime对象
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
// 4.将ZonedDateTime对象转化为LocalDateTime对象
LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
System.out.println(localDateTime);
java.time.LocalDateTime 》 java.util.Date
// 在上面的代码的基础之上,将LocalDateTime对象转化为java.util.Date
Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
System.out.println(date);
2.java.sql.Date和java.sql.TimeStamp的转化
它们两个内部都提供了直接转化为java.time.LocalDateTime的方法。
两者分别转化为java.time.LocalDate和java.time.LocalDateTime
// java.sql.Date 转化为 java.time.LocalDate
Date date = new Date(System.currentTimeMillis());
LocalDate localDate = date.toLocalDate();
System.out.println(localDate);
// java.sql.Timestamp 转化为 java.time.LocalDateTime
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
LocalDateTime localDateTime = timestamp.toLocalDateTime();
System.out.println(localDateTime);
3.java.util.Calendar转化为ZonedDateTime
需要先获取时区,再获取到calendar的instant数据,之后操作看代码:
Calendar cal = Calendar.getInstance();
// 获取时区 TimeZone
TimeZone timeZone = cal.getTimeZone();
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(cal.toInstant(), timeZone.toZoneId());
System.out.println(cal);
System.out.println(zonedDateTime);
4.LocalDateTime与String互相转换
使用DateTimeFormatter类提供静态常量,直接转化为指定的时间格式
/**
* LocalDateTime 和 String 互相转换
* DateTimeFormatter 代替 SimpleDateFormat
*/
LocalDateTime now = LocalDateTime.now();
// LocalDateTime -> String
String ISO_DATE_TIME = now.format(DateTimeFormatter.ISO_DATE_TIME);
System.out.println("ISO_DATE_TIME:"+ISO_DATE_TIME);
// String -> LocalDateTime
LocalDateTime parse = LocalDateTime.parse(ISO_DATE_TIME);
System.out.println(parse);
上面是通过DateTimeFormatter所提供的格式,把LocalDateTime转换为String。
下面提供自定义格式的String字符串进行显示:
LocalDateTime now = LocalDateTime.now();
// 自定义格式进行显示
String format1 = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss:SSS"));
System.out.println(format1);
String format2 = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"));
System.out.println(format2);
5.时间戳转化为指定时间格式的String
可通过java.time.Instant类转换,也可通过java.sql.Timestamp类转换
// 1.获取当前时间戳
Long time = System.currentTimeMillis();
// 2.1 通过Instant类获取到LocalDateTime类,在转化为指定格式的String
String format1 = LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
System.out.println(format1);
// 2.2 通过Timestamp类和DateTimeFormatter指定格式
String format2 = new Timestamp(time).toLocalDateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
System.out.println(format2);
这里值得注意的一点是:传递的Long类型的时间戳不能为null,这里的时间转换需要我们处理null的问题,而joda-time的时间转换,如果当前传递的Long类型时间戳为空,那么会自动返回当前pc的时间!(可以通过断点测试查看情况!)
多多益善~