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
4ZonedDateTime 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.377544OffsetDateTime
与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
4OffsetDateTime 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
4Timestamp 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
5nowDateTime.minusDays(1);
nowDateTime.minusWeeks(1);
nowDateTime.plusHours(1);
nowDateTime.plusMinutes(1);
//..加减 另一个时间
1
2
3
4nowDateTime = 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;
}参考文章