Java夏令时导致的问题

文章讨论了Java在处理中国1986-1991年夏令时时期的时间数据时出现的HOUR_OF_DAY报错,原因是不同JDK版本对Asia/Shanghai时区夏令时开始时间的处理差异。修复方案包括使用绝对时间、统一JDK版本、避免使用Date类型以及调整数据库连接时区。
摘要由CSDN通过智能技术生成

Java夏令时导致的问题

一、查询报错提示

报错提示: HOUR_OF_DAY: 0 -> 1

二、问题原因

通过网上查找资料得知,是中国有一段时间实施过夏令时导致的 1986-1991年 , 夏令时就是会在春夏之交当中某一天把时钟拨快一个小时的做法, 通过排查数据找到了一个有问题的日期** 1987-04-12 00:00:00这个日期是中国夏令时的开始时间,会在晚上把两点手动调成三点, 不同版本下 Asia/Shanghai 时区夏令时起始时间的不同,正是源于这种穷举配置,早期维护者认为中国标准时间的夏令时切换发生在0时,而后来又经证明发生在2时,新版本 JDK 及时修正了这个问题罢了。 所以mybatis返回时间做严格的校验会认为 1987-04-12**这一天不存在0点,应该直接从一点开始所以报错.

ps: 夏令时

​ 夏令时,(Daylight Saving Time:DST),也叫夏时制,又称“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。全世界有近110个国家每年要实行夏令时。

​ 1986年4月,中国中央有关部门发出“在全国范围内实行夏时制的通知”,具体做法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时,即将表针由2时拨至3时,夏令时开始;到九月中旬第一个星期日的凌晨2时整(北京夏令时),再将时钟拨回一小时,即将表针由2时拨至1时,夏令时结束。从1986年到1991年的六个年度,除1986年因是实行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。在夏令时开始和结束前几天,新闻媒体均刊登有关部门的通告。1992年起,夏令时暂停实行。

优点

高纬度地区由于夏季太阳升起时间明显比冬季早,夏令时确实起到节省照明时间的作用。

正在调时间适应夏令时的工人正在调时间适应夏令时的工人

不少零售商对夏令时持肯定态度。美国的糖果商院集团已经游说美国国会将夏令时延长到11月,因为万圣节是糖果销售最旺的季节,而家长们不希望孩子们在天黑以后还在外面游逛。

有人认为夏令时对患有夜盲症的人大有好处。除了节约了电,也让人们养成了早睡早起的好习惯

弊端

低纬度地区,夏令时作用不大。尤其这些地方在夏天十分湿热,夜晚降临时闷热无法入眠,而清晨正是睡眠的好时间。

当夏令时开始和结束时,人们必须将所有计时仪器调快或调慢;当夏令时结束时,某些时间会在当天出现两次,这些都容易构成混乱。并且影响航班的时间。

夏令时违背了设定时区的原意──尽量使中午贴近太阳上中天的时间。

中国实时夏令时开始结束日期

1986年至1991年,每年四月的第2个星期日早上2点,到九月的第2个星期日早上2点之间。

1986年5月4日至9月14日(1986年因是实行夏令时的第一年,从5月4日开始到9月14日结束)

1987年4月12日至9月13日;

1988年4月10日至9月11日;

1989年4月16日至9月17日;

1990年4月15日至9月16日;

1991年4月14日至9月15日。

三、问题修复方案

  1. 在数据库系统设计时,需要用到精确时间和计算的时候尽量使用 绝对时间, 然后让这个时间在不同的时区和系统中手动转换成本地时间
  2. 在问题复现的过程中发现 OracleJDK没有这个问题,OpenJDK存在这个问题, 开发过程中本地JDK和线上JDK版本尽量保持一致
  3. mybatis查询映射过程中,尽量使用JDK8版本的时间工具类LocalDate 不要使用Date (ps: 这种方式不兼容老的系统)
  4. mybatis查询映射过程中可以使用string类型来接收时间变量,自己手动转为时间类型,不同国家不同时区对同一日期的标识是不同的
  5. 可以通过修改数据库链接的时区来解决这个问题 由 serverTimezone=Asia/Shanghai改为serverTimezone=GMT%2B8

***文章参考博客: ***

https://www.ffutop.com/posts/2021-03-15-datetime-vs-calendar/

https://pooi.app/page/2/

ps: 绝对时间

格林威治时间1970年1月1日0时0分0秒相差的毫秒数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值