背景
- 源于一次bug的调试,测试输入用户的生日为:1991-07-24 保存后。刷新页面,生日变成了 1991-07-23。
- 经过排查,是夏令时和时区的概念不清楚导致的bug,这次就来系统的讲讲夏令时和时区的概念,和我们如何正确的处理时间。
概念
时区
由于世界各国家与地区经度不同,地方时也有所不同,因此会划分为不同的时区。
正式的时区划分包括24个时区,每一时区由一个英文字母表示。每隔经度15°划分一个时区,有一个例外,每个时区有一条中央子午线;例如,GMT属于“z”区,因此其时间后通常添加后缀“Z”(口语中用后缀“Zulu”)
夏令时
夏令时,表示为了节约能源,人为规定时间的意思。也叫夏时制,夏时令(Daylight Saving Time:DST),又称“日光节约时制”和“夏令时间”,在这一制度实行期间所采用的统一时间称为“夏令时间”。
一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。
冬令时
有夏令时就会有冬令时。高纬度和中纬度的许多国家在夏季到来前,把时针拨快一小时,新的时间就是夏令时,到下半季秋季来临前,再把时针拨回一小时,即形成冬令时。
夏令时和冬令时的影响
拿美国来说,美国各个地区的时间都不同,不像中国一样统一使用北京时间,美国一般以三月份第二个周日凌晨两点当成夏季的开始,十一月份第一个周日的凌晨两点当成冬季的开始。
所以在每年的三月份第二个周日凌晨两点过后,时间就会往前调快一个小时;同理,十一月份第一个周日把这一个小时调回来。
你也可以理解成美国那边,一年里面有一天只有23小时(夏天开始那一天),有一天有25小时(冬天开始那一天),其他时间每天都是24小时。
所以你会发现,夏天的时候,中国的北京时间(东八区)与美国太平洋时区(西八区)的时差是15小时,而到了冬天却变成16小时
讲解
- 中国区内开发java默认的时区是 Asia/Shanghai 也就是中国时区,而中国在1986年到1991年施行了夏令时,导致在夏令时的时间内,会少一小时的时间,1991-07-24 保存到数据库后变成了 1991-07-23 23:00:00 CDT。
方案
如果项目上没有跨国,可以在项目启动的时候。统一设置时区为东八区.当然也要注意数据库。
1
TimeZone.setDefault(TimeZone.getTimeZone("GMT+08"));
如果项目跨国了,推荐使用时间戳作为时间的记录值,数据库用Long类型,前台展示也更灵活