记java 夏令时的坑

背景:测试提了bug,用户生日修改后,回显比输入的日期少了一天。

分析问题

第一反应是是不是时区搞错了,少了8小时。看了下时区设置正确。

不是时区的问题,先去看下数据,看不一致是发生在数据入库前,还是读数据出现的问题。经过查数据库数据,发现数据库数据是正确的。

数据库数据正确,那就是返回数据的时候出现了问题。数据正确,时区设置也正确,那问题出在哪呢。

只能debug看看了,打入测试数据,2022-06-01,调接口入库,然后调接口查询,流程走下来没有问题啊,又多测了几个数据都没有问题。

这更奇怪了,那可能就是我的数据跟测试的数据有什么不同的,要来测试的数据,生日是 1990-04-29,测试一下果然有问题,存入数据库是1990-04-29读出后变成了1990-04-28。这就奇怪了,为什么会有这个情况。现在格式化用的是yyyy-MM-dd,决定打全看看,格式化 用 yyyy-MM-dd HH:mm:ss,打出来一看,格式化后是1990-04-28 23:00:00。怎么少了1小时。只能求助万能的度娘了。

原因:

原来是夏令时搞得鬼,想要搞清楚怎么回事,先要了解什么是夏令时:

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

而我国我实行过夏令时

我国解放前几年在部分地区也曾实行过夏令时。1986年4月,中央有关部门发出“在全国范围内实行夏时制的通知”,具体作法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时,即将表针由2时拨至3时,夏令时开始;到九月中旬第一个星期日的凌晨2时整(北京夏令时),再将时钟拨回一小时,即将表针由2时拨至1时,夏令时结束。从1986年到1991年的六个年度,除1986年因是实行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。1992年起,夏令时暂停实行。
1935年至1951年,每年5月1日至9月30日
1952年3月1日至10月31日
1953年至1954年,每年4月1日至10月31日
1955年至1956年,每年5月1日至9月30日
1957年至1959年,每年4月1日至9月30日
1960年至1961年,每年6月1日至9月30日
1974年至1975年,每年4月1日至10月31日
1979年7月1日至9月30日
1986年至1991年,每年4月中旬的第一个星期日2时起至9月中旬的第一个星期日2时止。具体如下:
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日。

也就是说在夏令时的时间内,日期是比真实时间少一个小时的,例如 1990-04-29 00:00:00 真实的时间 是 1990-04-28 23:00:00。

解决方案:

1.既然是因为夏令时的原因,时间少了一小时,导致了日期少了一天,那么我就判断如果是夏令时,就增加一天不就可以了,代码如下

 

TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");if(tz.inDaylightTime(entity.getBirthday())) {
  entity.setBirthday(org.apache.commons.lang3.time.DateUtils.addDays(entity.getBirthday(), 1));
}

 

2.看到有个文章说,jdk高版本支持了中国的夏令时才出现这个坑,1.8.0_131版本无法复现这个问题,待验证

 

posted @   木之舟  阅读(549)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示