东一区,date 和 date -u 显示时间相差 59分33秒?不是 1小时 吗?

举报
媒体服务小助手ultra 发表于 2023/09/13 10:10:35 2023/09/13
【摘要】 正常环境上 date 和 date -u 显示结果相差 1小时。而是异常环境上这两个命令显示结果相差 59分33秒,差 27秒 不到 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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。