Java8 Time包浅析
- 本文时对Java8 Time包中做一个简单的解析,适用于对Time包不甚了解/快速上手的人。
1. 从api上理解
| 包 | 说明 | 
|---|---|
| java.time | 核心时间类 | 
| java.time.chrono | 其他地方的纪年法 | 
| java.time.format | 时间格式化相关的类 | 
| java.time.temporal | 定义时间的基础接口 | 
| java.time.zone | 时区相关的类 | 
- 基类:
| 类 | 说明 | 
|---|---|
| Duration | 表示持续时间,从一个时间点持续到另一个时间点,比如:数据结构课从 8:00上到10:00 | 
| Instant | 时间点 | 
| LocalDate | 本地日期,默认时区,精确到日 | 
| LocalTime | 本地时间,默认时区,精确到秒 | 
| LocalDateTime | 本地日期时间,默认时区,上二者相加 | 
| MonthDay | 月份中的日期,不存年, 例如: 12月3日 | 
| OffsetDateTime | 在 ISO-8601日历系统中的UTC/格林威治偏移的日期时间,如2007-12-03T10:15:30+01:00。      旨在使用ZonedDateTime或Instant在较简单的应用中对数据进行建模。 当更详细地建模日期时间概念时,或者当与数据库或网络协议进行通信时,可以使用此类。 | 
| OffsetTime | 同上,但仅是时间:如 10:15:30+01:00 | 
| Period | 表示时间段,最小单位是天,开始结束时间点不确定,比如:国庆放7天假 | 
| Year | 年 | 
| YearMonth | 一年中的月,不存日, 例如: 2022年3月 | 
| ZonedDateTime | 时区的日期时间,精度为纳秒, | 
| ZoneId | 时区 ID,比如Asia/Shanghai | 
| DayOfWeek | 一周的天,枚举类 | 
| Month | 月,枚举类 | 
| DateTimeFormatter | 日期格式化 | 
2. 具体使用场景
2.1 创建时间及查询
- 创建年月日
| 1 | LocalDate now = LocalDate.now(); | 
- 创建时分秒
| 1 | LocalTime nowTime = LocalTime.now(); | 
- 创建完整体
| 1 | LocalDateTime nowDateTime = LocalDateTime.now(); | 
- 查询
| 1 | //可以查的非常细致,这里举例几个常用的 | 
2.2 时间比较
- 相同格式时间比较
| 1 | now.isAfter(birthday); | 
- 不同格式时间转化比较 - LocalDate/- LocalTime/- LocalDateTime三者不能相互直接比较。
 其中- LocalDateTime可以通过- toLocalDate()/- toLocalTime()进行转化再进行比较。
| 1 | nowDateTime.isAfter(ChronoLocalDateTime.from(now)); | 
- 与1.7用的时间java.util.Date进行比较
| 1 | Calendar calendar = Calendar.getInstance(); | 
2.3 时间转化
- 本包内互转 - ZonedDateTime与- LocalDateTime互转- ZonedDateTime相对与后者多表示时区,所以:
 - 1 
 2
 3
 4- ZonedDateTime BeijingTime = nowDateTime.atZone(ZoneId.of("Asia/Shanghai")); 
 //2022-10-27T15:11:41.466572+08:00[Asia/Shanghai]
 nowDateTime = BeijingTime.toLocalDateTime();
 //2022-10-27T15:12:05.377544- OffsetDateTime与- LocalDateTime互转- OffsetDateTime相对后者多表示偏移量,偏移量(- ZoneOffset) 的意思是时间相对与- UTC标准时区的偏移的时间。- UTC偏移量 仅仅只记录了时分秒而已,除此之外没有任何其他信息。举个例子 ,- +08:00的意思时超前于- UTC八个小时,而- -05:45意思是落后于- UTC五小时四十五分钟,偏移量最大- +18:00,最小- -18:00。- 偏移量和时区的关系。 - Asia/Shanghai,也称东8区- +08:00。但是在某些时间场景下时区有时会对应着与之前不同的偏移量。时区跟人类社会有关,比如说以后曹县很牛,可能就会有个- Asia/Caoxian,对应的偏移量可能就是- +07:40。
 - 1 
 2
 3
 4- OffsetDateTime offsetDateTime = nowDateTime.atOffset(ZoneOffset.MIN); 
 //2022-10-27T15:55:09.871589-18:00
 nowDateTime = offsetDateTime.toLocalDateTime();
 //2022-10-27T15:55:09.871589
- 转其他格式 - 与字符串互转之格式化 - 转时间戳
 - 1 
 2
 3
 4- Timestamp timestamp = Timestamp.valueOf(nowDateTime); 
 //时间戳转LocalDateTime
 nowDateTime = timestamp.toLocalDateTime();
 //2022-11-13T13:46:47.851677- 转时间点
 - 1 - Instant point = nowDateTime.toInstant(ZoneOffset.ofHours(8)); 
 
2.4 时间调整
- 加减天/周/月/年/秒/分/时 - 1 
 2
 3
 4
 5- nowDateTime.minusDays(1); 
 nowDateTime.minusWeeks(1);
 nowDateTime.plusHours(1);
 nowDateTime.plusMinutes(1);
 //..
- 加减 另一个时间 - 1 
 2
 3
 4- nowDateTime = nowDateTime.plus(Period.of(10,1,1)); 
 //-before-plus: 2022-10-27T17:08:29
 //--after-plus: 2032-11-28T17:08:29
 //同理有minus()方法。
- 最后放一张图总结一下  
- 缺陷 - 笔者在使用过程中发现新的时间包缺少对季节的相关处理:比如说查询当前时间在是哪个季节。 - 这里可以自己写一个简易的方法,示例如下。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- /** 
 * 查询当前月份所在季节code
 * @param month (1~12)
 * @return (1~4)
 */
 int getSeasonValueByMonth(int month){
 if (month == 1) {
 return 1;
 }
 return (month -1) /3 + 1;
 }
- 参考文章