时间线
Java中使用Instant表示即时时间,它替换了传统的java.util.Date。通过Instant.now()可以获取到当前的时刻。
//当前时间 05.26 16:26
System.out.println(Instant.now());
System.out.println(Instant.now().toEpochMilli());
输出:
2023-05-26T08:25:51.823791Z
1685089551833
它的结果并不是当前的本地时间,而是从1970.01.01——至当下距离的毫秒数。
下面的示例是关于Instant的部分使用方式:
Instant now = Instant.now();
//当前时刻
System.out.println(now);
//产生一个与当前距离为指定时间尺度的时间
Instant plus = now.plus(Duration.of(10, ChronoUnit.MINUTES));
//往后推进10分钟
System.out.println(plus);
Instant minus = now.minus(Duration.of(10, ChronoUnit.MINUTES));
//时光倒流10分钟
System.out.println(minus);
//获取两个时刻的时间距离
Duration between = Duration.between(plus, minus);
System.out.println(between);
//将一个时间 * 2
Duration duration = between.multipliedBy(2);
System.out.println(duration);
输出:
2023-05-26T08:45:00.452263Z
2023-05-26T08:55:00.452263Z
2023-05-26T08:35:00.452263Z
PT-20M
PT-40M
本地日期
Instant代表了当前时刻的绝对时间,但绝对时间并不是本地时间。Instant通常并不被用来表示年、月、日,而是使用LocalDate去表示本地日期。
给出LocalDate的部分使用方式
//当前日期
LocalDate day = LocalDate.now();
System.out.println(day);
//指定日期
LocalDate myDay = LocalDate.of(2023,1,1);
System.out.println(myDay);
//产生一个距离当前日期向后100天的日期
LocalDate date = myDay.plusDays(100);
System.out.println(date);
//产生一个距离当前日期倒流100天的日期
date = myDay.minusDays(100);
System.out.println(date);
//获取连个日期间隔的天数
long until = myDay.until(day, ChronoUnit.DAYS);
System.out.println(until);
//将一个日期范围对象转换为Stream流,步长为1个月
Stream<LocalDate> localDateStream = myDay.datesUntil(LocalDate.now(),Period.ofMonths(1));
System.out.println(localDateStream.collect(Collectors.toList()));
//通过日期调整器,将日期调整为当前月的第一号
System.out.println(date.with(TemporalAdjusters.firstDayOfMonth()));
输出:
2023-05-26
2023-01-01
2023-04-11
2022-09-23
145
[2023-01-01, 2023-02-01, 2023-03-01, 2023-04-01, 2023-05-01]
2022-09-01
Duration 和 Period 主要用来产生一个指定数量的时间单位。不同的是前者用来表示时间线Instant的时间单位,后者用来表示日期LocalDate的时间单位。
上面示例代码中的最后一行with()方法用来接收一个日期调整器,并返回调整后的日期。可以通过实现TemporalAdjuster接口来定义自己的调整器,或者直接使用TemporalAdjusters工具类为我们提供的各种调整器。
实现自定义日期调整器
//自定义一个日期调整器,调整日期向后推进10天
TemporalAdjuster adjuster = date -> date.plus(Period.ofDays(10));
LocalDate day = LocalDate.now();
System.out.printf("日期调整前%s\n",day);
System.out.printf("日期调整后%s",day.with(adjuster));
输出:
日期调整前2023-05-26
日期调整后2023-06-05
TemporalAdjuster是一个函数式接口,方法中的参数是Temporal类型,LocalDate实现了此接口,所以它的方法可以处理日期对象。
本地时间
LocalTime time = LocalTime.now();
System.out.println("当前时间:"+time);
System.out.println("小时:"+time.getHour());
System.out.println("分钟:"+time.getMinute());
System.out.println("秒:"+time.getSecond());
System.out.println("纳秒:"+time.getNano());
System.out.println("将时间向后推进1小时:"+time.plus(Duration.ofHours(1)));
输出:
当前时间:18:14:23.672654
小时:18
分钟:14
秒:23
纳秒:672654000
将时间向后推进1小时:19:14:23.672654
时区时间
每个国家甚至同一国家的不同地区的时区都是有可能不同的,比如中国还是白天,美国却是晚上。这个时候就体现到时区时间ZonedDateTime的重要性。
//中国UTC偏移量
ZonedDateTime dateTime = ZonedDateTime.now();
System.out.println("与UTC时间的差距:"+dateTime.getOffset());
//美国UTC偏移量
dateTime = dateTime.withZoneSameLocal(ZoneId.of("America/New_York"));
System.out.println("与UTC时间的差距:"+dateTime.getOffset());
//英国UTC偏移量
dateTime = dateTime.withZoneSameLocal(ZoneId.of("Europe/London"));
System.out.println("与UTC时间的差距:"+dateTime.getOffset());
输出:
+08:00
-04:00
+01:00
日期时间格式化器DateTimeFormatter
//hh是12小时表示 HH是24小时表示
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
System.out.println("hh:"+df.format(LocalDateTime.now()));
DateTimeFormatter df2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println("HH:"+df2.format(LocalDateTime.now()));
DateTimeFormatter df3 = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
LocalDateTime of = LocalDateTime.of(2021, 12, 27, 00, 00, 00);
System.out.println("YYYY:"+df3.format(of));
System.out.println("yyyy:"+df2.format(of));
输出:
hh:2023-05-26 07:06:32
HH:2023-05-26 19:06:32
YYYY:2022-12-27 00:00:00
yyyy:2021-12-27 00:00:00
通过上面的示例发现在使用格式化器的时候有些细节需要注意一下:
- YYYY 格式年的时候,如果月份中的日期在最后一个星期,那么会把年份算作下一年。
- HH/hh 格式化小时的时候,如果希望得到24小时表示的时间用
HH,如果希望12小时的表示则使用hh。