似乎发现了 jdk1.8 版本的一个date类的bug?

微笑兔 发布于 07/30 15:11
阅读 2K+
收藏 4

如上图所示,从度娘上了解到结尾的+0900和+0800表示时区的意思,但是 1940和1941年的时区与其他年份不同。这就导致了,spring在格式化返回时间是使用gmt+8类型 这两个年份始终不行 需要使用 gmt+9  不是和很懂 有没有大佬指教一下

以下是问题补充:

@微笑兔:补充一下 本地的jdk是 1.8.0_91 服务器的是1.8.0_131 (07/30 15:13)
@微笑兔:感谢大家的回答,但是在回答之前请看一下题目和一楼所张贴的demo代码,最最最简单的springboot项目,除图片上代码之外,没有任何自己编写的代码。并且我也让其他同事或朋友测试过,的确是不对的。我知道可能是我走进了死胡同,并且可能吧其他人也带进去了,所以恳请大佬在说明我错误的时候,阐述一下两个问题, (07/31 09:24)
@微笑兔:一:为何同样的日期不同的年份,对应的时区不同。二:为何spring配置jackson格式化返回对象的时间gmt+8配置对于其他年份的日期处理正常,但对于这40和41年,两个年份始终都会少一小时,要使用gmt+9才正常。如不嫌麻烦,烦请给我简述一下原理或源码,有推荐的问答或者博客也行,感激不尽 (07/31 09:26)
@微笑兔:感兴趣的小伙伴可以用一楼的代码测试一下。 (07/31 09:28)
@微笑兔:此贴终结,想知道的原因的可以 用维基百科 查询 中国时区 关键字。或者看一下我自己的最新回复。但确定两点,第一代码是没有问题的,第二也不是jdk或者spring的bug。 (07/31 12:46)
加载中
2
前端大师傅
前端大师傅

这个问题很简单,除了我楼上的是强制使用了asia/shanghai即东8区之外,而楼主使用的是gmt格尼威治天文台的gmt时间,如果是gmt时间系统会根据当时的所在时区与0点时间加或减时间,英国格尼威治天文台所在的经线为基准,将全球经线划分了24个时区,但中国是一个很特殊的情况,即30度一个时区在中国并不适用,也就是出现东9区的情况在1940年并不是bug。而是当时的时区是按正常的每30度一个时区来划分的,而后来新中国成立以后整个中国是东8区。虽然中国跨了好几个时区,仍是东8区。也就是在中国的任何一个地区都是+8。而不会出现+9,+8,+6,像我国的新疆地区应该是+6,但还是加8。

上面是原理,再说原因,jdk是不会有这种bug的,出现这个情况有两个原理:原因1就是当时的1940年在时区数据库里的时区对应关系找不到,所以采用30度加法来根据你的所在地的经度计算出来的东9,所以是+9。

 

爪爪爪爪爪
爪爪爪爪爪
回复 @微笑兔 : 你信他个鬼,他可是出了名的夏吉茂乱搞大师,被喷惨了,火的不得了。
微笑兔
微笑兔
回复 @前端大师傅 : 大佬 我这里说错了 其实不是这两年使用的东京时间 而是 这年推行了一个 叫夏令时的东西,人为调快一小时
前端大师傅
前端大师傅
回复 @微笑兔 : 是的,看到你发的维基百科里的介绍了,原因是1940是日伪日期使用的是东京东9区的时区。其实个人觉得最科学的还是用30度经线来划分时区,像我国的新疆和北京都使用东八区,这样也就造成北京时间7:30,新疆还是5:30还没天亮呢。特别是这种抗日战争时期时区变化的事情,本来是程序问题变成了历史和地理问题搞复杂了。
微笑兔
微笑兔
非常非常感谢你的回答,请问是否有相关的博客或者资料可以共享一下,谢谢
0
微笑兔
微笑兔

可能很多然看到的第一反应就是觉得我是个彩笔,肯定哪里弄错了,那我也不反驳,贴一个测试的结果

上图已经可以看到基础的时间都是相同的,但是返回到前端的时间不同。

微笑兔
微笑兔
如果各位觉得我验证错了 可以创建一个springboot的小demo测试一下,如果没问题,麻烦告知一下jdk的版本
0
薛柯基
微笑兔
微笑兔
这个也会遇到我的问题吧 可否麻烦你 用一个小demo验证一下
0
亭舸翁
亭舸翁

这应该是夏令时的问题

微笑兔
微笑兔
尝试了 在格式化的时候加上这个也不行 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
0
Onyourleft
Onyourleft

夏时令了解一下,使用"Asia/Shanghai"时区

微笑兔
微笑兔
尝试了不行,本身时间是没问题的 显示的也是对的 但是 40和41年创建出来的date时区不同
0
Bingdor
Bingdor

在1992年之前中国也采用夏令时的,所以会出现一天只有23小时或者25小时,因此java中的一天并不完全是24小时的。

微笑兔
微笑兔
但我只在41年和42年遇到这个问题……
0
caixu23
微笑兔
微笑兔
请问是否是按我上诉的配置进行了小的测试,可否说一下 springboot的配置 我多比一下自己的是否有问题
0
kakai
kakai

你再比对一下你的代码和我的代码,其实就是你的代码不是

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); 

这样设置的。你光设置了jackson的时区,肯定不对。

微笑兔
微笑兔
这个并非本地格式化的问题 我也没有说过格式化时间有问题 我质疑的是为什么 格式化后的相同日期 不同年份显示的 时区是不同的,而且我测试了多个年份 只有 40和41年有问题,请看清问题 谢谢你的回答
疯癫叟
疯癫叟
只设置TimeZone应该没用,需要设置RawOffset
0
dasha
dasha

果然有问题,java数据转json时,实际是转成时间戳。前端js显示时,根据时间戳转化成日期,下面测试相同日期两种语言转化时间戳:
测试时间:"1939-07-30 15:02:20","1940-07-30 15:02:20","1941-07-30 15:02:20","1942-07-30 15:02:20"
java中转时间戳后:[-960137860000,-928519060000,-896983060000,-865443460000]
js中转时间戳后:[-960137860000,-928519060000,-896983060000,-865447060000]
测试结果表明"1942-07-30 15:02:20" java转换成时间戳为-865443460000,js根据此时间戳转化成日期为"1942-07-30 16:02:20",多了一小时
结论:果然有问题,但是不知道哪个是对的

微笑兔
微笑兔
我已经知道答案了,可以看一下原贴我自己的回复,或者维基百科 查询 中国时区 不是代码层面的问题
微笑兔
微笑兔
谢谢你的测试和回答,有结论的话,请跟我分享一下
0
疯癫叟
疯癫叟

貌似要这样
 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            TimeZone defaultTimeZone = TimeZone.getDefault();
            TimeZone tz = TimeZone.getTimeZone("");
            tz.setID(defaultTimeZone.getID());
            tz.setRawOffset(defaultTimeZone.getRawOffset());
            format.setTimeZone(tz);

疯癫叟
疯癫叟
回复 @微笑兔 : 就是因为夏令时的原因,可能会导致出现CST和CDT两种时区的问题
微笑兔
微笑兔
谢谢你的回答 但我质疑的不是格式化时间的问题, 请看一下问题补充
返回顶部
顶部