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

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

问题描述


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


代码如下:


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、 对于时区,时间戳,夏令时来说,相互转换有时候特别容易混淆。


参考资料




相关文章
|
消息中间件 SQL API
Flink线上问题汇总篇(2)-时区不一致系统时间少8小时导致数据丢失问题
flink按月度汇总数据,月初时数据部分丢失问题
1725 0
|
7月前
|
SQL 关系型数据库 MySQL
实时计算 Flink版操作报错之遇到MySQL服务器的时区偏移量(比UTC晚18000秒)与配置的亚洲/上海时区不匹配,如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
存储 Java 程序员
实战:求年月日时间前后遇到的坑和解决方式
这周接到一个时间转换任务需要处理,本来没什么问题,后来完成后发现时间有偏差,又重写了一遍代码,感觉很有记录必要性,希望看过的小伙伴可以避坑。
实战:求年月日时间前后遇到的坑和解决方式
|
SQL Oracle 关系型数据库
[已解决]mysql查询一周内的数据,解决一周的起始日期是从星期日(星期天|周日|周天)开始的问题
[已解决]mysql查询一周内的数据,解决一周的起始日期是从星期日(星期天|周日|周天)开始的问题
|
JavaScript 前端开发
当天时间往后获取一周时间
当天时间往后获取一周时间
136 0
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
如何确定两个日期之间的工作日有多少天、计算—年中每周内各日期出现次数、确定当前记录和下一条记录之间相差的天数【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。本章节的三个需求:确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数有些许难度,不过建议还是学会比较好。
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
|
XML 安全 调度
时间戳:互联网上的日期和时间
日期和时间格式在 Internet 上引起了很多混乱和互操作性问题。本文档解决了在 Internet 协议中表示和使用日期和时间时遇到的许多问题,并提出了改进一致性和互操作性的建议。
792 0
在线时间戳转换工具的坑-同样的时间戳转为北京时间,转换结果受本机时区设置的影响...
在线时间戳转换工具的坑-同样的时间戳转为北京时间,转换结果受本机时区设置的影响...
291 0
|
PHP
php 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法
php 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法
901 0
|
Unix PHP
PHP中关于时间(戳)、时区、本地时间、UTC时间等的梳理
PHP中关于时间(戳)、时区、本地时间、UTC时间等的梳理 在PHP开发中,我们经常会在时间问题上被搞糊涂,比如我们希望显示一个北京时间,但是当我们使用date函数进行输出时,却发现少了8个小时。几乎所有的php猿类都必须对php中几个重要的时间转换等方法进行研究。
2197 0