修复Go程序在OpenWRT系统中无法正确处理时区的问题

陪她去流浪 桃子 阅读次数:111

OpenWRT在System页面设置好时区后会把配置数据写到 /etc/config/system 中:

1
2
3
4
5
root@cudy:~# cat /etc/config/system

config system
	option timezone 'CST-8'
	option zonename 'Asia/Shanghai'

中国的时区明明是UTC+8,这里的CST-8是个非常奇怪且少见的表示法(来自于 POSIX)1

  • “CST”是个任意可能的名字,并不一定代表中国标准时间(China Standard Time);
  • “-8”才是用于准确计算的部分,表示本初子午线往东“+8”时区。

时区会同时被写入到/tmp/TZ这个文件中:

1
2
3
4
root@cudy:~# ls -lh /tmp/TZ
-rw-r--r--    1 root     root           6 Dec 21 00:29 /tmp/TZ
root@cudy:~# cat /tmp/TZ
CST-8

但是Go的时区处理函数并不会读取这个位置23

1
2
3
4
5
6
7
8
9
// Many systems use /usr/share/zoneinfo, Solaris 2 has
// /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ,
// NixOS has /etc/zoneinfo.
var platformZoneSources = []string{
	"/usr/share/zoneinfo/",
	"/usr/share/lib/zoneinfo/",
	"/usr/lib/locale/TZ/",
	"/etc/zoneinfo",
}

甚至也不在环境变量“TZ”中。虽然会fallback到 /etc/localtime 中,但是在OpenWRT上,这是一个无效的软连接。

尝试在现有的Linux系统中拷贝一个能用的时区数据库文件(shanghai)并软连接过去,发现是可以使用的:

1
2
root@cudy:~# ls -lh /etc/localtime
lrwxrwxrwx    1 root     root          14 Dec 21 00:29 /etc/localtime -> /root/shanghai

好了,把它加在启动脚本里面开机自动软连接即可:

用C或者Zig写的程序貌似都有此问题,以上的做法能够一次性全部解决。

但是也有一个问题:时区不会随着在System页面上的修改而自动修改。不经常出国的话完全没有问题。我也不想安装全量的zoneinfo包。