其他分享
首页 > 其他分享> > 关于时间的那些事 - 中国也曾实行过夏令时,你知道吗?

关于时间的那些事 - 中国也曾实行过夏令时,你知道吗?

作者:互联网

之前遇到过一个由于标准时间/夏令时时间转换引起的问题,这里记录下来分享给大家。 大家都知道,地球上按照经度分成24个时区,每个时区相差一个小时。一般来说每个国家法定的时间都对应一个时区,比如中国用的东八区时间,韩国用的东九区时间,韩国时间比中国快一个小时。同时,很多高纬度国家都实行夏令时,即每到夏天把时钟拨快一个小时,每到冬天再把时钟拨慢一个小时,比如德国。 下图中可以看出很多国家现在或者曾经都实行过夏令时,蓝色表示正在实行,灰色表示曾经实行过,具体可查看wikipedia。 ![](http://www.icode9.com/i/li/?n=4&i=images/blog/202101/24/ec1a3ee82f0f72733de1e3fc0aae0ec1.png?,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=) 问题的原型是:在Postgres数据库中有一张表,表的定义如下: ``` CREATE TABLE public.datetimetest ( createdat timestamp NULL, id varchar NULL ); ``` 首先通过DBeaver执行如下语句向表中插入三条记录: ``` --001-- INSERT INTO public.datetimetest (id, createdat) VALUES('001', '1989-04-16 00:02:00.78'); --002-- INSERT INTO public.datetimetest (id, createdat) VALUES('002', '1989-04-16 00:50:00.450'); --003-- INSERT INTO public.datetimetest (id, createdat) VALUES('003', '1989-04-16 01:00:00.32'); ``` 然后执行如下语句查询: ``` --query-- select id, createdat, createdat::text as createdatstr from public.datetimetest; ``` 得到的结果如下: ![](http://www.icode9.com/i/li/?n=4&i=images/blog/202101/24/6d9dc3fd223e73b0b105edbb5d4c4f8f.png?,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=) 可以看到,记录001和002的createdat字段从00:02和00:50变成了01:02和01:50,这两条记录时间往后加了一个小时。但是,记录003却保持没变,和插入的时间是一致的。同时,可以看到,把createdat字段转成text类型,输出的值和插入的时间是一致的。 这是为什么呢? 开始还以为跟电脑或者数据库客户端IDE有关,后面发现在其他人电脑上有同样的问题。并且,用下面这段Java程序处理这个时间,出现了同样的问题,打印出来的时间也往后加了一个小时: ``` SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); Date date = sdf.parse("1989-04-16 00:02:00.78"); System.out.println(date); Sun Apr 16 01:02:00 CDT 1989 //打印结果,加了一个小时,timezone变成了CDT,中国的标准时间是CST ``` 后来mina同学发现,这个问题是**标准时间/夏令时**转换引起的。 那么什么是夏令时呢?夏令时英文全称Daylight Saving Time,缩写为dst,在上世纪初,为了节约能源而出现的计时方式,即每到夏天,把时钟拨快一个小时,每到冬天再把时钟拨慢一个小时,这种夏令时制在很多高纬度国家都在使用,比如德国,他们的timezone是Europe/Berlin,每到夏天他们会把时钟拨快一个小时,采用东二区的时间(CEST:Central European Summer Time ),夏令时结束,又把时钟拨慢一个小时,采用东一区时间(CET:Central European Time)。一个实际的例子就是:喜欢看球赛的同学可能有注意到,欧冠比赛的比赛时间在夏天是北京时间凌晨2:45am,冬天则是3:45am,其实都是当地时间8:45pm开始。 现在很多人可能不知道,其实**中国曾经也实行过夏令时(86年至91年)**,后来由于各种原因就取消了,全年采用统一的时间。关于为什么取消,网上有很多此方面的讨论。 现在计算机里面已经能够自动处理标准时间/夏令时的转换。比如用下面这段Java程序打印出当前时间: ``` System.out.println(new Date()); ``` 如果当前时间正处于标准时间/夏令时转换,程序会自动把当前时间加一个小时。 回到上面问题,我们把这个时间转成Java Date对象: ``` SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); Date date = sdf.parse("1989-04-16 00:02:00.78"); System.out.println(date); Sun Apr 16 01:02:00 CDT 1989 //打印结果,加了一个小时,timezone变成了CDT,中国的标准时间是CST ``` 由于这个时间刚好是执行标准时间/夏令时转换的那一个小时,在转成Java Date对象时,jdk认为这是一个标准时间,需要自动加一个小时,变成夏令时(类似于人为拨快一个小时动作)。 而其他时间没有这个问题,是因为jdk认为传入的时间就是一个夏令时时间,直接应用夏令时。 ``` SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); Date date = sdf.parse("1989-04-16 01:00:00.32"); System.out.println(date); Sun Apr 16 01:00:00 CDT 1989 //打印结果 ``` 这就是为什么发现有问题的时间都是在标准时间/夏令时转换的这一个小时。尽管中国已经不实行夏令时了,jdk还是能够自动处理曾经实行过的这一段时间。 **最后,当我们在处理时间时,如有必要,一定要把timezone信息存上,之前就遇到过由于压缩文件的时间戳不带timezone引起的问题,参见另一篇文章关于时间的那些事 - 文件的时间戳。 ** **另外,由于夏令时的存在,程序在处理某些时间时,可能会把标准时间转成夏令时时间(反之亦然),导致意想不到的结果。 ** 在研究过程中发现一个奇怪的现象:目前从各种资料上看到,中国实行夏令时的那几年(86-91年),标准时间到夏令时时间转换发生在凌晨2am,但是程序测试结果来看,转换是在0am,无论是java还是javascript,发现都是0am。 Java代码: ``` SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); Date date = sdf.parse("1989-04-16 00:02:00.78"); System.out.println(date); Sun Apr 16 01:02:00 CDT 1989 //打印结果可以看到,在夏令时转换的这一个小时,凌晨0点过的时间自动加了一个小时,变成了一点过. ``` Javascript代码: ``` new Date("1989-04-16 00:02:00.78"); Sun Apr 16 1989 01:02:00 GMT+0900 (China Daylight Time) ``` 同理,德国的夏令时转换也是凌晨2am,但是程序处理这个转换就是两点,和网上资料显示时一致的。 ``` TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Europe/Berlin"))); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); Date date = sdf.parse("2019-03-31 02:02:00.78"); System.out.println(date); Sun Mar 31 03:02:00 CEST 2019 //打印结果可以看到,在夏令时转换的这一个小时,凌晨两点过的时间自动加了一个小时,变成了三点过. ``` 有童鞋知道这个现象吗?欢迎分享。 ### Rerefences * https://www.timeanddate.com/time/change/china/beijing?year=1986 * 封面图片:https://www.starmilling.com/blog/whats-up-with-daylight-saving-time/

标签:02,00,16,夏令时,1989,时间,关于,实行
来源: https://blog.51cto.com/u_15067225/2901211