openSUSE Leap 15.2 Chromium 84.0.4147.125 的 Asia/Beijing 时区问题

起因是我自己做的一个网页, 意外的发现时间不对.

首先我电脑的时区设置是这样

timedatectl 
      Local time: Wed 2020-08-19 19:00:34 CST
  Universal time: Wed 2020-08-19 11:00:34 UTC
        RTC time: Wed 2020-08-19 11:00:34
       Time zone: Asia/Beijing (CST, +0800)
Network time on: yes
NTP synchronized: yes
RTC in local TZ: no

从firefox 控制台里面
输入
Date()
显示
"Thu Aug 20 2020 00:16:32 GMT+0800 (GMT+08:00)"
时区是对的

从chromium里面运行则显示 "Wed Aug 19 2020 16:17:54 GMT+0000 (GMT)"
时区不对

问题是, 没有从chromium里面找到时区设置, 那么如何解决chromium 的时区不对的问题??

大家帮忙测试下, 都是一样的结果吗?

我知道怎么复现问题了.

当systemd时区为 Asia/Shanghai 的时候, chromium时间正常.
当系统时区为 Asia/Beijing 的时候, chromium 时间不正常.

然后怎么确定是openSUSE还是chromium的问题??

没有 Asia/Beijing 这个时区吧……

sudo timedatectl list-timezones

没有 Asia/Beijing

所以这个现象可以解释了……指定了一个不存在的时区,所以 fallback 到了 UTC

@GlowDischargeTube @marguerite
图1: Beijing时区

首先我系统是有这个时区的. openSUSE 15.2

而且北京时区我很肯定 是在安装系统的时候 从地图里面选择的.
我检查了下, 我自己的两台电脑, 以及同事的一台电脑 全部是北京时区.

以及在Beijing时区, 我firefox显示时区正常.

图2: Firefox

(我问了一个安装arch的同学, 他没有Beijing这个时区.)

不明白这是怎么回事. :pleading_face:

图3: openSUSE安装的时候选择Beijing时区

Asia/Beijing 显然是个非标准时区,虽然我不知道为什么你那边会有这个时区,但是大多数程序不认这个是正常现象,使用一个非标准时区产生的效果应当是未定义的……只是 fallback 到 UTC 算是比较好的了……

该包打包时引入了一个 patch tzdata-china.txt (1.8 KB) 加入了 Asia/Beijing
但这个 patch 的内容应当没有被 iana 和多数应用所接纳……应当说存在问题……
根据 changelog

Mon Apr 24 12:04:12 CEST 2006 - kukuk@suse.de

- Fix china timezone mess [#163674]
- Don't include linux/stddef.h [#167964]

该 patch 于 2006 年被引入
@marguerite 我觉得这个 patch 存在不妥。是否应向 openSUSE 报告 bug?

@GlowDischargeTube 似乎这个 patch 只能在 Leap/SLE 生效。但两者 timezone 包的版本都是 2020a。

我感觉 patch timezone 包没啥问题,这个问题网上讨论也挺多的,Java 那边好像都官方修复了。感觉可能是忘记了 patch systemd 造成 systemd timedatectl fallback 了,毕竟 2006 年没有 systemd…再有不同版本 systemd 可能 callback 有问题导致有的就有有的就没有

根据 systemd/src/basic/time-util.c,现在 systemd 获取的是 /usr/share/timezone/zone1970.tab 里的 timezone 信息,而以前获取的是同一文件夹下的 zone.tab 里的 timezone 信息。

zone.tab 里是有 Asia/Beijing 的,而 zone1970.tab 里面是没有的。

也就是说下一步要看一下 chromium 的源码是从哪个 tab 里获取的 timezone 信息,也许用的也是 zone1970.tab。或者更简单的是把 zone1970.tab 也 patch 掉。

1赞

Chromium 用的是 icu 包来实现 Date() 的,icu 包具体取时区的代码在这里:

具体点在 Linux 下是 /etc/localtime 和 /usr/share/zoneinfo/Asia/Beijing

1赞

@zhiliao

搞了一下午,有点儿弄懂这中间的联系了:

openSUSE 上 Firefox 和 chromium 都是利用系统的 libicu67 包来获取时间的,libicu67 又是通过运行时访问 timezone 包的内容来获取时区的。之前我说的 zone.tab 和 zone1970.tab,它们里面记载的其实是时区的物理经纬度,本身并没有什么用…

而我在 timezone 的代码层面把 Asia/Beijing 完全的 Link 为 Asia/Shanghai,也就是说除了名字不一样实际都一样(正常也应该是这样,解压开 tzdata2020a 里面有个 asia 文件,详细的说明了 Asia/Shanghai 这个 timezone 在各个历史时期的差异,也说明了它现在就是北京时区),在 chromium 里运行 Date() 依然不对,而保持 Asia/Shanghai 就没有任何问题。Firefox 始终没问题。

也就是说,chromium 代码可能针对 Asia/Shanghai 做了特殊的判断,导致只有 Asia/Shanghai 的时候你得到的反馈才对才是 Local Time,其它返回的是 UTC 时间。

https://source.chromium.org/chromium/chromium/src/+/master:v8/src/objects/js-date-time-format.cc

1赞