设计给老外发通知邮件的时候,遇到了时区问题。
我看了一下表,现在北京时间 19:00,西雅图比北京晚 15 小时,于是 19 - 15 = 4
,西雅图是 4:00。打开世界时钟验证一下,西雅图果然是 4:00,计算正确。
北京时间 19:00 有一节课,就发邮件给西雅图的老师说,你在 4:00 有节课,是不是就可以了?
好像是没毛病。不过印象中我用的美股交易软件,提醒过用户美国进入夏时令什么的然后美股开盘收盘都提前一小时。记不太清了,我就请教了曾在北美留学的同事。她说了几句也没解释清,又问了旁边的歪果仁,还是没讲明白。我一看算了,老外这脑子不一定行。还是问问在美国定居的老同学孙忱吧,就发了条微信给他。
很快便收到回复,孙忱几句话就讲明白了 daylight saving 的本质,不愧是谷歌的大神。但我自己还想进一步搞清楚,为什么要有夏令时这么奇怪的设定?
刚才说了,今天(9 月 6 日)北京时间 19:00,西雅图是 4:00,相差 15 个小时。但到了冬季,北京 19:00 对应的就是西雅图 3:00,相差就不是 15 小时了,而是 16 小时。
时间是协同大家步调的重要参考,必须力求精确,夏令时从哪天开始,到哪天结束,必须要有一个说法。我上网一查,说法倒是有,只是远不止一个。长图预警:
看完上面的图,犹如电影结束后长长的演员表,恭喜你坚持等到了彩蛋。
通过上面的长图可见,夏令时的起止日期,在不同年份不一样,不同国家也不一样,甚至同一国家的不同地区也有差别,拿美国为例:
美国不实行夏令时的州及领土包括:夏威夷、美属萨摩亚、关岛、波多黎各、美属维京群岛以及除去纳瓦霍人保留地社区之外的亚利桑那州。
至此终于明白,时区偏移可不是简单几条规则就能搞定的,不由得产生了敬畏。
程序一般都可以获取到用户时区,以 JavaScript 为例:
Intl.DateTimeFormat().resolvedOptions().timeZone;
如果是在北京,这个返回值就是字符串 Asia/Shanghai
,如果在西雅图就是 America/Los_Angeles
然后用这个时区字符串就可以做转换:
time = new Date("2019-09-06T19:00:00"); // 本地北京时区晚上 7 点
time.toLocaleString("en-US", { timeZone: "America/Los_Angeles" });
// 转换成西雅图时间,是凌晨 4 点
夏令时差 15 个小时,是对的。下面试试非夏令时,我们换一个冬天的时间:
time = new Date("2019-12-06T19:00:00"); // 本地北京时区晚上 7 点
time.toLocaleString("en-US", { timeZone: "America/Los_Angeles" });
// 转换成西雅图时间,是凌晨 3 点
从结果看到,程序能自动识别出夏令时/非夏令时,特别省心对不对。
关于夏令时的由来,英文 daylight saving 表达的很清楚,就是为了节约日光。少浪费日光,就能少耗费电灯的电能。乍一看有道理,但综合起来看其实弊大于利,网上关于它的吐槽有很多,我就不啰嗦了。
说到底,还是节约意识太强害的。太会过日子了。有一件事我是查了资料才知道,那就是中国——这个非常节俭的国家——也实行过好几年的夏令时。就发生在我小时候,而我竟然完全没有印象!小孩子真的是只知道玩啊。