手动安装tzdata2020d 文件本身并不能解决此问题。但是以下应该(使用golang:alpine docker 映像成功测试):
mkdir tz
cd tz
wget https://www.iana.org/time-zones/repository/releases/tzdata2020d.tar.gz
tar -xvf tzdata2020d.tar.gz
zic -b fat -d zoneinfo/ europe
cp zoneinfo/Europe/Berlin /usr/share/zoneinfo/Europe/Berlin
其他解决方法包括:
原因
此问题是由zic 应用程序的更改引起的;在2020b 发布的版本之前,默认为fat 模式,该模式可以正确处理应用程序。现在默认是 thin 并且 go 不支持这种格式(没有这个 patch)。不幸的是,LoadLocation 函数静默失败(返回不正确的区域信息)。
无论何时使用 2020b 或更高版本的时区文件,都可能出现此问题(除非包维护者在运行 zic 时覆盖了默认值)。
zic详情
iana 将时区信息分发为一系列text files 以及一些applications。其中一个应用程序是zic,它将文本文件处理成二进制文件(RFC 8536),然后部署到/usr/share/zoneinfo。
This commit 将默认输出格式从 fat 更改为 slim。这样做的结果是使用 2020b 或更高版本生成的时区文件将无法被 Go 正确读取(除非它们是使用 -b fat 参数创建的)。
去修复
这已在 Go 1.15.4 和 1.14.11 中得到修复。
已提出issue,该问题已由最近的commit 部分解决(该提交的主要目的是减小time/tzdata 包的大小,但也应该解决此问题)。有关修复的另一部分,请参阅 this issue。
测试
以下应用程序演示了该问题:
package main
import (
"fmt"
"time"
)
func main() {
b, err := time.LoadLocation("Europe/Berlin")
if err != nil {
panic(err)
}
t := time.Date(2020, 10, 23, 11, 00, 00, 00, time.UTC)
fmt.Printf("1: %s %s\n", t, t.In(b))
t = time.Date(2020, 10, 31, 11, 00, 00, 00, time.UTC)
fmt.Printf("2: %s %s\n", t, t.In(b))
}
截至 10 月 19 日的输出(Docker 下的 Alpine 3.12)是:
1: 2020-10-23 11:00:00 +0000 UTC 2020-10-23 13:00:00 +0200 CEST
2: 2020-10-31 11:00:00 +0000 UTC 2020-10-31 13:00:00 +0200 CEST
这是不正确的,因为第 31 位应该是 CET(Alpine 3.8 生成正确的结果)。