共计 3589 个字符,预计需要花费 9 分钟才能阅读完成。
你好呀,我是歪歪。
给大家分享一个我最近发现的有点意思,然而卵用不大的小知识点。
先给你搞个程序看一下:
public class MainTest {public static void main(String[] args) throws Exception {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = simpleDateFormat.parse("1900-01-01 08:00:00");
System.out.println(simpleDateFormat.format(date));
}
}
你说下面的程序逻辑就是一个简略的工夫格式化,你说输入后果是什么?
只是须要瞟一眼就晓得,必定是输入这个后果呀:
1900-01-01 08:00:00
然而,你把下面的程序拿进去,间接跑起来,你会发现输入后果居然是这样的:
1900-01-01 08:05:43
过后就懵逼了。
我晓得时差 8 小时,是因为有时区问题。
我晓得时间差 1 小时,是因为有夏令时的起因。
然而这里差了 5 分 43 秒,有零有整,就让我有点摸不着头脑了。
下面这个案例就是一个读者分享给我的,他们在数据库外面默认工夫是 1900-01-01,再加上时区问题,刚好变成了 1900-01-01 08:00:00,于是在通过程序做数据迁徙的时候就踩到了这个莫名其妙的工夫问题。
同时他还给我附送了一个对于这个 bug 的链接:
https://bugs.openjdk.java.net…
我乍一看,这个 bug 还挺新的呢,属于往年提出来的。
认真又看了一眼发现是和之前的 bug 反复了:
然而这里提到了起因:
他说能够看一下这个链接 https://www.timeanddate.com/time/zone/china/shanghai?year=1900
这外面,在 1900 年的时候,产生了一个变动:
The timezone offset was UTC +8:05:43 hours all of the period.
尽管我没太看明确具体是什么意思,然而我看到了“5 分 43 秒”:
我了解就是因为时区的变动,导致工夫产生了重置。
接着我顺藤摸瓜,在 stackoverflow 上找到了这个:
https://stackoverflow.com/que…
过后我就震惊了。
这个 10 年前被提出的问题竟然曾经被浏览过 746k 次了,十分热门的问题了,我竟然没留神到过:
这个问题具体是这样的:
你就大略瞟一眼,我给你翻译翻译。
提问者说,他发现 1927-12-31 23:54:07 到 1927-12-31 23:54:08 之间差了 353 秒,按理来说应该是 1 秒才对啊?
然而把工夫改成上面这样,又失常了:
String str3 = "1927-12-31 23:54:07";
String str4 = "1927-12-31 23:54:08";
我把程序粘进去你也能够跑一下,看看后果十分的神奇啊:
public static void main(String[] args) throws ParseException {SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str3 = "1927-12-31 23:54:07";
String str4 = "1927-12-31 23:54:08";
Date sDt3 = sf.parse(str3);
Date sDt4 = sf.parse(str4);
long ld3 = sDt3.getTime() /1000;
long ld4 = sDt4.getTime() /1000;
System.out.println(ld4-ld3);
}
然而当我跑了一遍之后,我发现:我去,说好的 353 秒呢?
跑进去怎么是 1 秒呢,毫无故障啊:
我甚至狐疑是 jdk 版本的问题,于是我换了 jdk 9,11,15 都跑了一下,都是 1 秒。
这就很奇怪了啊。
感觉这个问题提的就有问题啊。
然而当我读了上面最高赞的答案之后,我才好像窥见了一点端倪。
这个答复比拟长,我先全副截图下来给你看看:
比拟长的起因是作者批改了几次答复。
为什么会批改答复呢?
且往后看吧,所有的答案都藏在这外面。
我选要害的给你说。
首先看第一段:
他说(1927 年)12 月 31 日的时候,上海的时区产生了变动。
而对于 1927 年上海的详细情况,他附上了一个超链接,这个超链接就是后面呈现的网站,点进去之后是这样的:
然而这个外面显示:
No further time changes in 1927 in Shanghai
翻译过去就是:1927 年上海的工夫没有进一步变动。
这特么就和他上面说的那一坨内容对不上了啊?
他上面说,在 1927 年底的午夜时候,时钟往回走了 5 分 52 秒。因而,”1927-12-31 23:54:08″ 实际上产生了两次,而 Java 取的是第二次的的时刻,因而存在差别。
看到这里其实我都懵逼了,这玩意前后不符啊,于是我有接着开始搜寻。
直到我发现了这个:
https://coolshell.cn/articles…
这也是十年前的文章。
这外面作者把过后网站截了个图:
当年的截图显示:
在 1927 年 12 月 31 日 23:59:59 时,往后面的一秒应该是 1928 年 1 月 1 日 0:0:0,然而这个工夫被往后调整了 5 分 52 秒,而成了,1927 年 12 月 31 日的,23:54:08,于是,实现了 352 秒的穿梭。
这阐明了什么?
阐明数据产生了篡改,有人篡改了网页上的信息!
到底是怎么回事呢?
咱们回到 stackoverflow 接着往下看:
这是他第一次批改答复,因为 History changes…
历史发了变动了 …
他这里说,如果用 TZDB 的 2013a 版本的数据,原来的问题将不再体现出完全相同的行为。
在 2013a 中,后果将是 358 秒,过渡工夫为 23:54:03,而不是 23:54:08。
他提到了一个 TZDB,这是个啥货色呢?
我也不晓得,然而我搜寻了一下。
他应该说的是这个的货色。
https://www.iana.org/time-zones
看名字你也晓得了,它是一个时区数据库,外面应该是保护的时区相干的数据。
也就是说,在这个时区数据库外面,用 2013a 版本的数据,后面的代码就是另外一种输入了。
也就是说数据的确产生了变动。
而要害的答复在于下一次编辑:
History has changed again…
历史再次发生了变动。
在个时区数据库外面,2014f 版本中,变动的工夫曾经移到了 1900-12-31,当初只是一个 343 秒的变动。
343 秒?
不就是咱们后面的 5 分 43 秒吗?
好了,当初时差能对上了,343 秒,然而工夫还是没对上啊。
咱们的测试工夫 1900-01-01 08:00:00,他这里写的工夫是 1900-12-31。
差了整整一年呢?
好,咱们看他最初一次编辑的内容:
我集体了解他要表白的意思是这样的。
Java 为了在时区上统一标准,所以来了个一刀切的政策。
对立的规范就是让 UTC 时区下 1900 年之前的任何霎时都是规范工夫。
至于产生的时差嘛 …
就在最开始的时候补上去吧。
所以,1900-01-01 00:00:00 加上 8 小时时差,是 1900-01-01 08:00:00,在这个根底上事后加上 27 年后来自 1927-12-31 那个午夜因为工夫回拨带来的 343 秒。
1900-01-01 08:05:43,我集体认为就是这样来的。
而后面 stackoverflow 外面对应的那个程序,咱们当初执行是输入 1,然而在 10 年前,输入后果的确是 353。
就像我把程序改成这样:
最终的输入后果不是 1,而是 -342。
工夫,产生了“倒流”。
好了,又是一个没啥卵用的知识点。
最初,再补充两个冷常识。
第一个是我在 jdk bug 列表外面追溯了一下,能找到最早提出相干问题的工夫是 2005 年:
https://bugs.openjdk.java.net…
在这个外面,官网是这样回复的:
这个问题不会被修复,以防止任何兼容性问题。
意思就是:问题我晓得了,然而这玩意不太好弄,bug 先变成 feature 吧,就先这样吧。
别问,问就是有历史起因在外面。
第二个冷常识是,后面提到的,时区在 1927 年产生了变动。
你晓得为什么吗?
我在某网站上找到了这样的形容:
https://zh.wikipedia.org/wiki…
1928 年,就是民国 17 年。
那一年,南昌起义暴发,中国人民解放军成立。
那一年,毛主线在井冈山建设农村反动根据地。
那一年,星星之火,已成燎原之势。
最初说一句
好了,看到了这里了,转发、在看、点赞轻易安顿一个吧,要是你都安顿上我也不介意。写文章很累的,须要一点正反馈。
给各位读者敌人们磕一个了:
本文已收录自集体博客,欢送大家来玩。
https://www.whywhy.vip/