【问题标题】:How to fix broken tzdata2020c timezone database for alpine?如何修复损坏的 tzdata2020c 高山时区数据库?
【发布时间】:2021-02-04 22:20:54
【问题描述】:

我刚刚偶然发现了一个用于 alpine 的 tzdata2020c 软件包的错误。在 2020 年 10 月 25 日下周日计划更改夏令时后,它不会计算欧洲/柏林的正确时间。版本 tzdata2020c 使用 CEST,例如2020 年 10 月 31 日和欧洲/柏林时区,而 CET 是正确的。

有人知道如何手动添加 tzdata2020d 数据库的新版本,该数据库可用here

我用 Go 编写的应用程序在 2020 年 10 月 31 日使用 tzdata2020c 错误地使用了欧洲/柏林的 CEST:

同一应用程序在 2020 年 10 月 31 日使用 tzdata2020a 正确使用了欧洲/柏林的 CET:

【问题讨论】:

  • 我已经复制了这个问题; the playground 与 docker 镜像 golang:latestgolang:alpine 的性能一样。但是,如果我在 alpine 映像 (apk add tzdata) 中安装时区数据,则结果不正确(所有时间都在 CEST 中)。运行 export ZONEINFO=/usr/local/go/lib/time/zoneinfo.zip 可以解决此问题(采用这种方法可以快速解决)。

标签: go alpine tzdata


【解决方案1】:

手动安装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

其他解决方法包括:

  • 升级到 Go 1.15.41.14.11
  • 使用ZONEINFOenvironmental variable 选择不同的区域文件(例如export ZONEINFO=/usr/local/go/lib/time/zoneinfo.zipzoneinfo.zipgo installation 中)。
  • 在您的应用中包含tzdata 包(并且不要在容器中安装 tzdata - 仅当时间包在系统上找不到 tzdata 文件时才使用该包)。
  • 使用从scratch 构建的容器(结合上述选项之一)
  • 固定 uses 2020a 或更早的 alpine 版本(即 alpine:3.8)(请注意,版本 3.8 已超过其 End of Support 日期)。

原因

此问题是由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.41.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 生成正确的结果)。

【讨论】:

【解决方案2】:

在 alpine:3.9 图像上遇到了同样的问题,并根据英国人的回答设法解决了这个问题。谢谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    • 2011-04-15
    • 2016-08-24
    • 1970-01-01
    • 2013-09-11
    • 2021-04-21
    • 1970-01-01
    相关资源
    最近更新 更多