本文目录
1 Instant
2 ZoneId
3 LocalDateTime
4 ZonedDateTime
5 关系图解
6 时间格式化
Instant 表示基于世界标准时间(UTC)的时间线上的某一个时间点,通常用作事件的时间戳。
Instant 取值为 基于世界标准时间 从 1970/01/01 00:00:00.000 到 某一个时间点 经历的时长(秒 + 纳秒),例如:
instantValue = 0s:表示 1970/01/01 00:00:00.000 (UTC) 或 1970/01/01 08:00:00.000 (UTC+8)
instantValue = 3600s:表示 1970/01/01 01:00:00.000 (UTC) 或 1970/01/01 09:00:00.000 (UTC+8)
注意:当通过指定时间点的方式创建Instant对象时,参数值应该是基于世界标准时间的值。
ZoneId 表示时区,例如:北京时区为东八区,即 UTC+8 。
LocalDateTime 表示一个不含时区信息的时间,其组成包含两个部分:LocalDate 和 LocalTime
LocalDate 仅包含日期部分(即 年 月 日)
LocalTime 仅包含时间部分(即 时 分 秒
通过1、2两节内容可知,要表示一个时间,需要 Instant 和 ZoneId 两个信息,即 基于世界标准时间的时间点 和 要表示的时间的时区 信息,这样,才可以计算得到一个相应的时间信息,例如:
instantValue = 3600s:表示 1970/01/01 01:00:00.000 (UTC)
zoneId = UTC+8:表示 东八区
localDateTime = 1970/01/01 01:00:00.000(UTC) + 时区偏移量(+8小时) = 1970/01/01 09:00:00.000 (UTC+8)
通过上述说明可知,LocalDateTime仅保存一个时间信息,在构造其对象时,提供的 Instant 和 ZoneId 信息,只是为了计算对应时区的一个时间信息,LocalDateTime 对象构造完成后,即表示一个时间,但并不保存时区信息。因此,也可以通过直接指定时间的方式构造 LocalDateTime 对象。
由于 LocalDateTime 对象不保存时区信息,因此,就无法从其中获取 Instant 信息。因为没有时区信息,无法确定 LocalDateTime 表示的是哪里的时间,因此,无法确定对应的世界标准时间的时间点。例如:
1970年01月01日 16:00:00
只有一个时间信息,没有时区信息,无法知道这个时间是北京时间,还是纽约时间。
在实际应用过程中,LocalDateTime 对象通常用于时间格式化(显示时间),而不用于不同时区的时间转换。
LocalDateTime 表示一个无时区信息的时间,而 ZonedDateTime 表示一个包含时区信息的时间。
当为 LocalDateTime 附上时区信息时,即可转化为 ZonedDateTime 对象。
Instant 也是一个仅包含时间信息的对象,因此,为 Instant 附上时区信息时,同样,可转化为 ZonedDateTime 对象。
由于 ZonedDateTime 包含时区信息,因此,可以从其中获取 Instant 对象信息,例如:
1970年01月01日 16:00:00 UTC+8
明确是东八区的时间,则对应的世界标准时间为 1970年01月01日 08:00:00 ,其 instantValue = 28800秒。

上图描述了 Instant、ZoneId、LocalDateTime 和 ZonedDateTime 之间的关系。
需要说明的是,Instant 和 ZoneId 结合得到 LocalDateTime 步骤中,ZoneId 仅用于确定时间偏移量,从而计算得到该时区对应的时间,并由 LocalDateTime 对象保存时间信息,而时区信息并没有在 LocalDateTime 对象保存。
常见的时间异常情况,大部分是由于时区问题没有处理正确导致。这种情况,在网络传递时间数据的时候,时常发生,其根本原因是两端基于不同的时区对时间进行处理,例如:
服务端:基于UTC,返回时间字符串信息,如 timestamp = 1970/01/01 08:00:00,对应北京时间为 1970/01/01 16:00:00。
客户端:基于本地时区,处理服务端返回的时间字符串信息,即 将 1970/01/01 08:00:00 当成北京时间,导致时间差8小时。

时间异常图示
解决方案:以Instant值作为时间值进行存储和网络传输,各端以Instant值为基础,各自构造其所需时区的时间对象。

解决方案图示
在 Java 8 之前,通常使用 SimpleDateFormat 对时间进行格式化,但 SimpleDateFormat 不是线程安全的类,即 在多线程环境下使用共享的 SimpleDateFormat 对象(例如 static 对象),则可能发生异常情况。
因此,为了保证线程安全,在每个线程中,需要创建一个 SimpleDateFormat 对象,保证不同线程之间不会共享一个 SimpleDateFormat 对象。或者,通过 ThreadLocal 方式,达到线程隔离效果。
在 Java 8 之后,JDK 提供了 DateTimeFormatter 类,用于提供时间格式化方法。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/148017.html