记录一次时间戳、夏令时、时区线上问题分析

简介: 记录一次时间戳、夏令时、时区线上问题分析

问题描述


问题:输入时间戳、时区,返回一个带时区的时间字符串?


代码如下:


long timestamp = 1647489600000L; // 2022-03-15 12:00:00  Asia/Shanghai
String timeZoneName = "America/New_York";
Instant instant = Instant.ofEpochMilli(timestamp);
ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.ofInstant(instant, ZoneId.systemDefault()),
TimeZone.getTimeZone(timeZoneName).toZoneId());
System.out.println(zonedDateTime);
ZonedDateTime zonedDateTime1 = ZonedDateTime.of(LocalDateTime.ofInstant(instant, ZoneId.systemDefault()),
TimeZone.getTimeZone("Asia/Shanghai").toZoneId());
System.out.println(zonedDateTime1);


输出结果如下:


image.png


几个类简单说明一下:


  • Instant 可以将时间戳转换为本地日期/时间 LocalDateTime


  • JDK 8 之前,Java使用 java.util.TimeZone 来表示时区。而在JDK 8里分别使用了 ZoneId 表示时区,ZoneOffset 表示 UTC 的偏移量。


  • ZonedDateTime 是一个带时区的日期类。


夏令时(DST)


我们知道,纽约是 西五区,上海是 东八区  那么应该和我们的时间相差13 个小时(因为一个时区就是相差一个小时),但是我们得到的结论,确实是相差了 12 个小时,是不是有点怀疑自己。


image.png


再来看看,居然是 11 点,明明是相差 12 个小时,为什么说是比北京时间慢 14 小时这就是由于当前时间是夏令时导致的。


一个特殊的例子:


ZonedDateTime zonedDateTime2 = ZonedDateTime.ofInstant(instant,
    TimeZone.getTimeZone("GMT-05:00").toZoneId());
System.out.println(zonedDateTime2);
// 结果:2022-03-16T23:00-05:00[GMT-05:00]


如果我们使用 GMT-05:00 来获取时区的时间,那么就不会触发夏令时,可能会和你想象的结果不同。


换句话说 America/New_York 可能是 GMT-05:00 也可能是 GMT-04:00 这个具体要看 LocalDateTime 是否在夏令时的时间区间内.


如何通过 America/New_York 获取到 GMT-xx


一个简单的方法


ZonedDateTime of = ZonedDateTime.of(LocalDateTime.now(ZoneId.of("America/New_York")), ZoneId.of("America/New_York"));
System.out.println(of.getOffset().getId());


输出:


-04:00


思路来源于


image.png


说明一下:


ZonedDateTime 包括 LocalDateTimeZoneId 我们将 -04:00 加上 GTM 前缀就可以了,而且已经包含夏令时的处理。


总结一下


1、如果按照用户侧,百度上的时间来算,由于现在是夏令时,所以 America/New_York 方式的时区才能正确的获取本地时间。


2、 具体的 Java 几个日期类的差别,大家可以看看参考资料中的文件。


3、 对于时区,时间戳,夏令时来说,相互转换有时候特别容易混淆。


参考资料




相关文章
|
6月前
|
关系型数据库 MySQL Java
SpringBoor连接mysql数据库取数据库中时间格式是12小时制的时间,如何显示成24小时制
SpringBoor连接mysql数据库取数据库中时间格式是12小时制的时间,如何显示成24小时制
83 0
|
消息中间件 SQL API
Flink线上问题汇总篇(2)-时区不一致系统时间少8小时导致数据丢失问题
flink按月度汇总数据,月初时数据部分丢失问题
1702 0
|
4月前
|
Prometheus 运维 监控
子机UTC时间与NTP时间差值(s) 参数监控指标
子机UTC时间与NTP时间差值(s) 参数监控指标
102 0
|
5月前
一文搞懂:两个日期的时间间隔
一文搞懂:两个日期的时间间隔
56 0
|
6月前
|
弹性计算 运维 Shell
解析日期和时间
【4月更文挑战第29天】
46 1
|
C语言 C++
C++ 如果设置日期 & 时间基础篇
C++ 如果设置日期 & 时间基础篇
|
存储 Java 程序员
实战:求年月日时间前后遇到的坑和解决方式
这周接到一个时间转换任务需要处理,本来没什么问题,后来完成后发现时间有偏差,又重写了一遍代码,感觉很有记录必要性,希望看过的小伙伴可以避坑。
实战:求年月日时间前后遇到的坑和解决方式
|
SQL Oracle 关系型数据库
[已解决]mysql查询一周内的数据,解决一周的起始日期是从星期日(星期天|周日|周天)开始的问题
[已解决]mysql查询一周内的数据,解决一周的起始日期是从星期日(星期天|周日|周天)开始的问题
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
如何确定两个日期之间的工作日有多少天、计算—年中每周内各日期出现次数、确定当前记录和下一条记录之间相差的天数【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。本章节的三个需求:确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数有些许难度,不过建议还是学会比较好。
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
|
C语言 C++
C++ 如果设置日期 & 时间基础篇
C++ 标准库没有提供所谓的日期类型。C++ 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构,需要在 C++ 程序中引用 <ctime> 头文件。