缘起
这几日闲来无事撸代码, 无意中发现一桩趣事. 原以为是一个 Java 的 bug, 没想到经过一系列死磕, 挖掘出了一段和中国历史乃至人类文明相关联的人文故事, 不禁唏嘘感叹一番.
这件事的缘起很简单, 我在实现计算两个日期天数距离逻辑的过程中, 发现了一个很诡异的事情, 同样的起始日期, 用 python 和 Java 计算出的结果居然不一样!
例如, 计算一个 1990 年 1 月 1 日到 1990 年 9 月 4 日之间的天数, 用 python 计算如图:
得出天数为 246. 可以看到, python 的 API 设计简单.
用 Java 计算则不同了, 众所周知 Java 推荐的 Calendar API 不是一般的麻烦, 实现函数如下:
按照这个逻辑测试如下:
WTF!? 得出的天数居然是 245 天? 为什么和 Python 算出来的不一样? 我马上实际数了一下, 应该是 246 天, Python 算的结果是对的!
仔细核对了程序实现, 没毛病啊? 难道有精读损失?
狐疑(懵逼)
进而加入如下输出:
什么鬼? 这 0.0416666667 天跑哪里去了? 需知:
也就是说, Java 计算的时间和实际正好差了一个小时!
无独有偶, 各种百度后, 居然发现了和我有类似疑问的兄弟:
https://ask.csdn.net/questions/241889 https://ask.csdn.net/questions/241889
然而这个提问下并没有靠谱的答案!
这样看, 似乎很像时区上出了问题, 然而并不是, 前后 Calendar 对象的时区完全一致! 都是 Asia/Shanghai!
由此难免要想, 难道 Java 代码有 Bug? 把这一个小时给吃了? 好吃吗? 啥味道?
然而, 用同样的函数, 计算 990 年 1 月 1 日到 1990 年 12 月 4 日之间的天数, 有一切正常了!
心中万马奔腾啊!
经过一番探索, 我又写了如下代码:
惊奇地发现:
进而又发现:
由此我灵机一动, 又写了一段代码, 找到从 1900 年至今所有当天长度非 24 小时的日期!
此中必有蹊跷!
豁然
然而这对于没文化的我来说, 实在是一件不可理喻的事情. 只能从源码入手了!
找源码的过程就不再赘述了, 总之, 时间的偏移来自于一个 zoneOffsets 的数组, 而这个数组中除了因为时区而产生的偏移外, 还有一个神秘的 DST_OFFSET!
找到这里, 这个谜团即将揭晓了!
啥是 DST_OFFSET 呢?
没错, daylight saving offset, 也就是夏令时!
也就是说, 中国的 1990 年 4 月 15 日这天里, 人为地将时间拨快了一个小时, 1990 年 9 月 16 日这天再拨慢回来. 进一步说, 中国的 1990 年 4 月 15 日这天确实是 23 个小时, 1990 年 9 月 16 日这天也确实是 25 小时, Java 没搞错!
也就是说之前找到的所有非 24 小时的日期, 都是中国政府 (或国民政府) 施行夏令时调整的日期, 这段历史断断续续地持续了半个多世纪! 而 Java 的 Calendar API 将其忠实地记录了下来.
关于夏令时详情见百度百科 https://baike.baidu.com/item/夏令时/1809579?fr=aladdin .
哈哈哈, 真相揭晓, 好感慨好激动. 所以说, 这并不是 Java 的 bug, 而正是 Java 严谨的体现! Calendar API 确实设计的很烂很不友好, 但并不代表其中有 bug, 相反地, 这也正体现了其中的工程师精神.
这就引出了一段已经被淡忘的历史, 很多 90 年出生的朋友可以问问父母, 90 年和 91 年是我国至今为止实行夏令时的最后两年, 我国曾经也想向美国等西欧国家学习, 充分利用太阳下的时光! 年轻的小朋友问问你们的父母, 一定能勾起他们的一段回忆!
这就是隐藏在 Java 代码中的一段历史, 一段已经被遗忘的人文故事!
想了解这段历史的同学可戳:
还记得大明湖畔的夏令时吗? https://mp.weixin.qq.com/s/V6Un2Kanwzcq898DDpdBvg
只要刨根问底, 一定有意想不到的收获! 感觉解决了个大谜团!
来源: https://juejin.im/entry/5b49c1e76fb9a04fc9373942