26.5 jdk8的日期时间类
[TOC]
本文主要参考 Java编程的逻辑 一书 26章。
针对jdk8以前的时间日期类设计的不足,jdk8引入了java.time包来作为新的日期时间处理类。
了解jdk8的时间类之前,先复习下时间的基本知识。
- UTC Universal Time Coordinated 协调世界时
- GMT Greenwich Mean Time 格林尼治标准时间
在日常使用过程中可以认为UTC 和 GMT可以对等使用。
26.5.1 表示日期和时间
jdk8中表示的类有多个,主要的有:
类 | 作用 | 备注 |
---|---|---|
Instant | 表示时刻 | 对应jdk7之前的Date,可通过Epoch Time 纪元时相互转换 |
LocalDateTime | 获取当前系统的日期时间(内部不记录时区) | 可以认为由LocalDate和LocalTime组成 |
LocalDate | 获取当前系统的日期 | |
LocalTime | 获取当前系统的时间 | |
ZoneId | 时区,"+01:00"和"Europe/Paris" | ZoneId除了处理与标准时间的时间差还处理地区时(夏令时,冬令时等) |
ZoneOffset | 时区,只处理 "+01:00" | ZoneOffset是ZoneId的子类,只处理与格林尼治的时间差 |
ZoneDateTime | 特定时区的日期和时间 | LocalDateTime内部不记录时区,ZoneDateTime记录 |
26.5.1.1 Instant
除了以下的生成转换方法,Instant有很多时刻的比较和计算方法,大多比较直观,这里就不多讲了。
//1.1 直接获取当前时刻
Instant instant = Instant.now();
//1.2 通过纪元时(Epoch Time)获取
Instant instant1 = Instant.ofEpochMilli(System.currentTimeMillis());
//1.3 Date也表示时刻,所以instant 和date可以通过Epoch Time 纪元时转换
Instant instant2 = Instant.ofEpochMilli(new Date().getTime());
Date date = new Date(instant2.toEpochMilli());
//1.4 根据时区返回ZoneDateTime
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("GMT+8:00"));
26.5.1.2 LocalDateTime
//2.1 直接获取
LocalDateTime localDateTime = LocalDateTime.now();
//2.2 指定年月日获取
LocalDateTime localDateTime1 = LocalDateTime.of(2019,2,15,20,20);
// 2.3 同时LocalDateTime有很多方法:例如单独获取年\月\日\小时\分钟\周几
int year = localDateTime.getYear();
int dayOfYear = localDateTime.getDayOfYear();
DayOfWeek dayofWeek = localDateTime.getDayOfWeek();
26.5.1.3 ZoneId/ZoneOffSet
ZoneId/ZoneOffSet的区别。
ZoneOffSet只处理与标准时的时区差,ZoneId除了处理与标准时的时间差,还处理地区时(夏令时,冬令时等时间调整)
(ZoneOffset) ZoneId.of("+01:00")
//ZoneOffset只处理("+01:00")类型的时区问题,所以下面的代码会抛出异常
(ZoneOffset) ZoneId.of("Europe/Paris")
26.5.1.4 LocalDate/LocalTime
可以认为LocalDateTime由LocalDate和LocalTime两部分组成。LocalDate负责处理日期,LocalTime负责处理时间。
26.5.1.5 ZonedDateTime
与LocalDateTime的区别是,ZonedDateTime内部记录了时区,而LocalDateTime没有。
因此LocalDateTime转Instant需要指定ZoneOffSet而ZoneDateTime不需要。
LocalDateTime.now().toInstant(ZoneOffset.of("+01:00"));
ZonedDateTime.now().toInstant();
26.5.2 日期时间格式化 DateTimeFormatter
Jdk8中的日期时间格式化类主要是java.time.format.DateTimeFormatter
。它是线程安全的。
- DateTime转String
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String patternString = formatter.format(ZonedDateTime.now());
- String 转DateTime
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime2 = LocalDateTime.parse("2019-03-03 23:49:12", formatter);
26.5.3 时间修改调整
修改时间有两种方式,一种是直接设置绝对值,一种是在现有值得基础上相对增减。
Jdk8得大部分日期时间类都支持这两种方式。
Jdk8得日期时间类大都是不可变类,修改操作是通过创建返回新对象来实现得。原来得对象不会改变。
LocalDateTime localDateTime = LocalDateTime.now().minusDays(10).plusDays(9).plusWeeks(2);
计算下周二的两种方法:
//先plusWeek加一周,再调用with指定时间
LocalDateTime lo = LocalDateTime.now().plusWeeks(1).with(ChronoField.DAY_OF_WEEK, 2);
//使用 TemporalAdjusters 工具类的next方法直接指定时间
LocalDateTime lo1 = LocalDateTime.now().with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
第二种方法使用了TemporalAdjusters工具类中的next方法。此工具类中还有许多类似的简便方法:
TemporalAdjusters.lastDayOfMonth();
TemporalAdjusters.firstInMonth(DayOfWeek.TUESDAY);
TemporalAdjusters.nextOrSame(DayOfWeek.TUESDAY);
TemporalAdjusters.next(DayOfWeek.TUESDAY);
26.5.4 时间段得计算
Jdk8中得时间段得计算主要有两个:Period 和 Duration
- Period表示日期之间得差(年月日),包含to* 方法将差值转成*
- Duration表示时间差(日时分秒),包含to* 方法将差值转成*
两个类得to* 方法得到得是整数,使用舍一法。
Period period = Period.between(LocalDate.of(2019, 9, 1), LocalDate.of(2008, 8, 1));
Duration duration = Duration.between(LocalTime.of(10,10),LocalTime.now());
26.5.5 Date /Calendar 对象转换
- 不含时区信息得转换其实是利用纪元时转换(LocalDateTIme)
- 含有时区的转换一般是指定时区后使用纪元时转换。
网友评论