东一区,date 和 date -u 显示时间相差 59分33秒?不是 1小时 吗?
我们的业务拓展到了欧洲,来自东一区挪威奥斯陆的同事发现一个问题。
正常环境上 date 和 date -u 显示结果相差 1小时。而是异常环境上这两个命令显示结果相差 59分33秒,差 27秒 不到 1小时。这是为什么呢?
分析了一下 date 以及 localtime 的源码,发现时间如何显示,取决于程序调用 localtime 时候设置的时区是什么。
应用程序通过 time、gettimeofday 或者 lstat 等从内核查到的时间(或者文件访问时间 atime、mtime、ctime 等),都是用 UTC 时间的秒来表示的。0秒代表 1970-01-01 00:00:00,以此类推。如果要将这个 UTC 时间的秒转换成人类可读的具体日期时刻,那么我们需要知道这个时间是在哪个时区展示的。
假设我们从内核获取到的 UTC 时间是 2020-01-01 00:00:00。大家都知道中国使用东八区时间,也就是 UTC 时间 +8小时,所以在中国展示出来就是 2020-01-01 08:00:00。如果我们在东一区,那展示时间的时候只需要 +1小时,那么在挪威展示出来就是 2020-01-01 01:00:00。
而做这个转换工作的,就是 localtime 这一组函数了,他们从 TZ 这个环境变量里获取当前时区信息。如果这个变量没有设置,则会从 /etc/localtime 对应的时区文件里获取。
/etc/localtime 这个文件通常这都是一个软连接,指向 /usr/share/zoneinfo 目录下某个具体的文件(参见 man tzset)。/usr/share/zoneinfo 这个目录下存放了每一个时区的描述文件。UTC 时区就是在 /usr/share/zoneinfo/UTC 文件里描述的,而北京时间对应 /usr/share/zoneinfo/Asia/Beijing 这个文件。
说到这里其实就明白了。
上面的 date 命令就相当于 TZ=:/etc/localtime date,获取到 UTC 时间之后,会根据 /etc/localtime 描述的时区信息将时间转换成人类可读的时间格式。
而 date -u 命令就相当于 TZ=UTC0 date。TZ=UTC0 这是一个特殊的表达方式,简要的表示了 UTC 时区的时间转换方法。
具体的使用方法,可以参阅 GNU 文档:http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
你可以使用 TZ=Asia/Beijing date 命令,将时间展示为北京时间。
这时候 tzset 会去 /usr/share/zoneinfo/Asia/Beijing 这个时区文件里加载时区信息。
通过 zdump -v /usr/share/zoneinfo/Asia/Beijing 命令,我们可以看到这个时区文件里的内容。
大家可以看到这里还有夏令时的设置,比如下面两个命令显示的区别就是夏令时造成的。
CST - China Standard Time,CDT - China Daylight Time。
关于夏令时,可以参考帖子:http://3ms.huawei.com/hi/group/2691763/thread_3128491.html
关于上面同事提到的问题,我们尝试了使用 TZ=Asia/Beijing date 来跟 date -u 对比,发现两者时间差异是精确的 8小时。
那这差的 27秒 是从哪里来的呢?在网上百般搜寻之后,我们找到了下面的链接。难道是因为闰秒?
第27次闰秒来临:http://news.sohu.com/20161230/n477388117.shtml
应对Linux下的闰秒:https://www.cnblogs.com/luxianghao/archive/2017/02/04/6339470.html
经检测,异常环境的 /etc/localtime 链接的文件是 /usr/share/zoneinfo/right/Europe/Oslo,这个文件是包含闰秒的。
而正常环境的 /etc/localtime 链接的文件是 /usr/share/zoneinfo/Europe/Oslo,不包含闰秒。
针对这个问题,修改 /etc/localtime 链接指向 /usr/share/zoneinfo/Europe/Oslo 即可解决。
关于 /usr/share/zoneinfo 下目录结构的解析,请参考下面链接:
https://mm.icann.org/pipermail/tz/2015-February/022024.html
END
- 点赞
- 收藏
- 关注作者
评论(0)