最近清明节放了三天假(4月4/5/6), 国外某一版本在6号需要发布。 我呢, 刚好有事没去加班。 结果加班的同事发现了某时间显示出现了差一错误, 需要我在电话中定位,根据同事描述,我当时怀疑是夏令时问题。 下面, 我来简要描述一下。
问题现象: 某服务端给某客户端返回了一个时间, 客户端显示的时候, 发现多了一个小时。 奇怪的是, 同样的服务端和同样的客户端, 在中国国内就没有问题, 但是, 在国外就有问题。
问题原因: 服务端返回的时间已经考虑了夏令时, 而客户端把这个时间当成普通的时间, 又考虑了一次夏令时,所以结果多1个小时。
影响分析: 多了1个小时, 不准。
规避/解决办法: 服务端不变, 统一由它考虑夏令时问题, 客户端不进行转换, 仅负责简单显示。
由于这个bug比较简单, 所以我就不具体描述场景了。 这个问题潜伏了4年之久, 那么多测试的同事怎么没有发现呢? 主要是因为, 我们目前交付的多数是国内版本, 不存在什么夏令时问题, 即使交付了一些国外版本, 也可能刚好就处在非夏令时时段, 所以呢, 这个bug一直没有暴露。
下面, 我们来了解一下夏令时,我们以北京时间(GMT+8)为例, 运行下面程序:
#include <stdio.h> #include <time.h> int main() { time_t t = 0; time(&t); struct tm *p = localtime(&t); printf("%d\n", p->tm_isdst); char szBuf[100] = {0}; strftime(szBuf, sizeof(szBuf),"Data:\n%Y-%m-%d\nTime:\n%H:%M:%S",p); printf("%s\n", szBuf); return 0; }结果为:
0
Data:
2015-04-07
Time:
22:31:35
好,我们以柏林时间为例吧。 把Windows时区设置为GMT+1的柏林时区(且打开夏令时), 运行上面相同的程序, 得到的结果为:
1
Data:
2015-04-07
Time:
16:32:09
按理说, 柏林时间应该比北京时间慢7个小时啊, 但为什么上面的结果显示才慢6个小时呢, 原来, 柏林地区进入了夏令时了, 时间会比以前快一个小时。 需要注意的是, 如果你在冬天运行这个程序, 那就是非夏令时时间了(柏林地区2015年的夏令时时间为3月29日到10月25日)
对于程序员来说, 夏令时是一个经常碰到的概念, 百度的介绍也很多, 我就不copy了, 下面, 我仅简要说说它的原理:
在柏林冬天的某一天, 上午9点, 阳光“刚刚好”, 你该上班了。 等到到了柏林夏天, 8点的阳光“刚刚好”, 这个时候本来你是不需要上班的, 因为没有到9点嘛, 但这样一来, 8点的"刚刚好"的阳光就被浪费了, 所以德国柏林强行规定, 把现在这个“刚刚好”的8点定义为9点, 这样修改后, 你还是9点开始上班, 而且阳光“刚刚好”。 所以, 我们说, 在夏天这段时间内, 柏林进入夏令时制, 时间比预定的快了一个小时, 有很多好处啊, 还是迎着朝阳上班, 阳光"刚刚好", 还是背着日落下班。
下面, 我们来玩转一下夏令时,亲自在Windows上做一下实验:
以柏林的2015年为例:
(1)将Windows设置为GMT+1的柏林时区, 将时间调到:2015年3月29日01点59分59秒, 再过一秒, 实际上到2015年3月29日03点00分00秒了, 而不是2015年3月29日02点00分00秒了, 这样就形成了一个小时的时间空缺。
(2)将Windows设置为GMT+1的柏林时区, 将时间调到:2015年10月25日01点59分59秒,再过一秒, 就是2015年10月25日02点00分00秒。 将时间调到:2015年10月25日02点59分59秒, 再过一秒,还是2015年10月25日02点00分00秒。这样一来, 实际上有两个小时点被挤在一起了。
我国也曾经采用过夏令时, 但后来被废止了, 也好, 不然现在的程序猿可又要麻烦很多