首页 > 代码库 > 一个关于时间的故事(通过历史分析解决程序问题)
一个关于时间的故事(通过历史分析解决程序问题)
一日在给一个时间转换函数getUTCTimeFromLocal(StringsLocalTime)做单元测试。作为一个有很多年开发经验的我,用例不能太小家子气吧。于是给了个“1921-1-1 00:00:00”作为输入参数。结果发现,其他的用例执行都是OK,就这个古老的日子NG了。
用到的函数也很基础:
DateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (String date : dateString) {
System.out.println(date + "=" + dateTimeFormat.parse(date));
}
难道是Java的SimpleDateFormat类不支持太远的时间?我又换了其他一些输入参数,发现1929年以后的时间都是对的啊。1928年就出问题了。
难道是夏令时?但是网上又查了下,虽然世界上有110个国家在实行夏令时,但我国在1986到1991年间实行了6年的夏令时。(由于省电效果不抵需要适应时间的弊端,1992年4月5日后不再实行)何况现在差的时间远没有1个小时。
仔细看了下,虽然输出结果和预想的不太一样。但似乎差的不是很多。日期和小时都是对的,差的只是分和秒。更精确的说是就差了5分52秒。对于这个结果,我很无语,做java这么多年,还从来没碰到这个事情。这个时间点很奇怪,是年末哦。这个又让我想起了“闰秒”这个天文事件。由于地球自转的不均匀性和长期变慢性(主要由潮汐摩擦引起的),会使民用时和原子时之间相差超过到±0.9秒时,为了保持民用时和原子时的同步,由国际计量局统一规定在年底或年中对协调世界时增加或减少1秒的调整。就把世界时向前拨1秒(负闰秒,最后一分钟为59秒)或向后拨1秒(正闰秒,最后一分钟为61秒)。2012年我国曾宣布我国7月1日进行闰秒调整,届时将现7:59:60。自1971年首次增加闰秒以来,已经调整过了24个闰秒。但是现在差的不是1秒啊。所以闰秒的假设也被否定了。
然后,我又做了2个实验。1,在.NET下执行了类似的函数。二是在linux下执行了同样的函数。结果都没有出现类似情况。
Linux下的java问题同样出现。.NET下没有问题。看来是Java类库自身的实现问题了。但是现在已经是java7了。如果是bug的话,也该早就被发现了哦。
那这个是中国这个东八区才有的现象吗?我调到了东7和东9,发现是正常的。看来这个是跟东8区有关了。而且跟那个年代似乎存在着关联。1927年似乎是中华民国刚成立,会不会那个时候出了什么事情呢。看来搞计算机不但要上知天文下知地理。历史知识也得过关啊。当然,如果没有这些也不要紧。有搜索引擎就行。
大家都知道,中国古代我们的老祖宗是怎么计时的吗?大家应该不陌生,很多的武侠片,历史剧中大家都经常听到“天干物燥,小心火烛”的更夫的惯用口令。没错,古代都是用更来表示晚上时间的。戌时作为一更,亥时作为二更,子时作为三更,丑时为四更,寅时为五更。三更就是半夜---晚上12点。古代的24小时是分成12个时辰。每个时辰是用1个地支来表示的(共12个地支,和12生肖对应)。每个时辰是2小时。但时辰是怎么计算的呢。
去过北京故宫的朋友应该还有印象,在大殿前有个叫日晷的计时工具,它把一个时辰平均分成了八份,一份叫做一刻。所以午时三刻大概就是11点45分左右,这个时候,太阳最高,人的影子最短。一天当中“阳气”最盛的时候。,这个时候是鬼魂最不敢出来的时候。古代的人们就是用这个进行时间的记录的。说到这里,大家可能会有疑问,日晷计时需要有太阳啊。晚上怎么办呢。特别是更夫他们是靠什么知道时间,并通知其他人的呢。关键就在“铜壶滴漏”。这种计时装置最初只有两个壶,由上壶滴水到下面的受水壶,液面使浮箭升起以示刻度。保持上壶的水位恒定是滴漏计时准确的关键。打更人就是在家守着这个“铜壶滴漏”,一到时间就出去打更告诉其他人。因为水受温度影响比较明显,后来这个滴漏也有改进。开始用水银,后来就用细沙。沙漏就这样诞生了。
似乎扯得有点远,我们回到近代吧。1912年之前,中国各地并没有统一的标准时间。在王朝时代,国家的标准历法由皇庭颁布,而中国传统历法同时依赖于日月两个天体的运动,并以实际天文观测为准,因此历时标准都以朝廷所在地(钦天监的观测点)的经纬为准。民国7年(1918年),中央观象台提出将全国划分为5个标准时区 。
l 中原时区(GMT+8),(东经120度经线之时刻为标准);北京、江浙等
l 陇蜀时区(GMT+7),(东经105);陕西、四川、云南、贵州等:
l 回藏时区(GMT+6),(东经90);蒙古、甘肃、青海等。
l 昆仑时区(GMT+5:30),(东经82);新疆及西藏之西部等。
l 长白时区(GMT+8:30),(东经127);东北。
民国17年(1928年),国民政府统一中国,原中央观象台的业务由南京政府中央研究院的天文研究所和气象研究所分别接收。天文研究所编写的历书基本上沿袭中央观象台的做法,仍将全国划分为5个标准时区,只是在一些特别的天文时间点上,不再使用北平的地方平时(local mean time,简称LMT),而改以南京所在的标准时区的中原时区标准时替代(中原时区的标准时刻,由位于上海租界的徐家汇观象台提供,再由电报总局、铁路局以电报形式或者广播电台形式将标准时刻传递到各地所属机构,这个时间就是我们现在使用的UTC+8时区的时间,它和北平的LMT时间相比差了5分52秒)。其中,地方平时就是指,在指定的经度范围内使用一致时间的地方太阳时,他的一致性仅取决于测量用的钟表准确性。地方平时从19世纪初期开始逐渐被采用,这些地区都不再使用地方太阳时或日晷的时间。这个时间段就是1912年~1927年之间。从1928年起,相当于对我国的中原时区(北京,上海,江苏等)的时间进行了校正,和国际接轨了。
到了1935年,全国统一使用UTC+8时区的时间,但仍然分成之前的5个时区。当然在抗战时期,曾经一度以陇蜀时区作为全国的统一时间。抗战结束后即又恢复中原时区。
新中国成立的头几年,全国各地所用的时间比较混乱。五时区还在实行,但是北京时间的概念已经出来了。初期使用的“北京时间”不是我们今天理解的北京时间,也就是说它不是标准时,甚至不是北京地方的平太阳时(以太阳连续两次经过某地之下中天的平均时间间隔,更为精确,地球自转倾角和椭圆轨道决定了每天的视太阳时是不一样的),而是北京地方的视太阳时。(视太阳时:也就是真实的太阳连续两次经过某地相同之中天的时间间隔)。建国初期,百废待兴,出现这样的情况是可以理解的。到1954年,标准时(UTC+8)的北京时间终于明确下来。至此,除了西藏和新疆外,其他地区都划归为东八区。当然香港澳门,台湾因为地理位置原因,也正巧都属于东八区范围内。再补充一点:北京时间并不是在北京确定的,而是由位于陕西临潼的中国科学院国家授时中心原子钟确定的。
现在即使是西藏和新疆,官方(政府机关,学校,单位)都使用北京时间(只要是中国境内)。当然当地人在家里有可能会使用当地时间。经度上乌鲁木齐属于东6区,要比北京时间晚2个小时。
前面也提到过80年底搞过6年的夏令时。简单总结一下:
1986年至1991年,每年从4月中旬的第一个星期日2时整(北京时间)到9月中旬第一个星期日的凌晨2时整(北京夏令时)。除1986年因是实
行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。
政府动员实行夏令时的初衷是为节约能源而早睡早起。
但1992年4月5日后不再实行。中国不适合实行夏令时的原因:
中国西部的四川、云南、新疆等地实行的都是北京时间,相当于全年实行夏令时。所以,夏时制只对东北和华北起作用。
中国大多数的平民都已习惯北京时间。实行夏令时对于他们来说难以接受,觉得这是多此一举。
夏时制使铁路和航班需要每年修改时间表,造成麻烦。
目前全世界范围内,俄罗斯2011年3月27日开始永久使用夏令时。美国从三月到11月实行夏令时。欧洲除了冰岛之外都执行夏令时。日本,韩国,台湾地区和我国现在不执行夏令时。
说到这里,其实谜底早已经揭开了。1928年1月1日0时0分0秒,上海改使用UTC+8时区替代了原来的本地时间。变成了1927年12月31日12时54分8秒,从而有5分52秒的差距。我们可以到专业的时间认定网站去查看。
http://www.timeanddate.com/time/zone/china/shanghai
Time Changes in Shanghai over the years
在1927年之前,“Nochanges, UTC +8:05:52 hours all of the period”
1927年之后,“Nochanges, UTC +8 hours all of the period”
终于多出来的5分52秒终于找到了。
所以说再1927年以前的时间中,每年:08:00:00~08:05:51(北京时间)这段时间实际上是不存在的。那个年代中国地区使用的是本地时间,本地时间比GMT足足少了5分52秒。
这个事情我明白了一个道理。很多时候,计算机的问题,被一定非得通过计算机的方法才能解决。或者说,换个思路,换个角度,很多看起来很难解释的问题也能够迎刃而解的。希望和大家一起从中得到启示,所以特撰此文,共享之。
一个关于时间的故事(通过历史分析解决程序问题)