在golang中全局设置时区

我正在尝试为我的应用程序修改 golang 时区

我看了一下时间包,初始化时区发生在

时间/zoneinfo_unix.go @initLocal

该函数只是尝试读取环境变量TZ,如果有效则加载它

如果不是,它会回落/etc/localtime,如果它无效,它会回落到UTC


到目前为止我已经尝试过

1- 工作正常 - 但我不想使用这些方法中的任何一种 - :

  • 在我的 docker 文件中,我将 ENV 传递给容器,TZ = Africa/Cairo

  • 进入容器 bash,运行$ export TZ = Africa/Cairo

2-没用

  • 在我的应用程序初始化中(应用程序初始化在一个单独的包中,正在主导入),我使用 os.SetEnv("TZ", "Africa/Cairo")

当我简化 main 并使用 os.SetEnv("TZ", "Africa/Cairo") 而不导入除“os - time”之外的任何其他包时,它按预期工作


关于如何使第二种方法起作用的任何想法?

Docker 镜像:golang:1.11.2


米脂
浏览 370回答 4
4回答

白猪掌柜的

您可以使用从您的应用程序内部实现您想要的os.Setenv("TZ", "Africa/Cairo"),重要的是您必须在任何其他包使用time包中的任何内容之前调用它。如何确保?创建一个除了设置时区之外什么都不做的包(稍后你可以向它添加其他东西,但对于我们的例子来说这就足够了)。像这样:package tzinitimport (    "os")func init() {    os.Setenv("TZ", "Africa/Cairo")}首先在你的包中导入这个tzinit包,如下所示:mainpackage mainimport _ "path/to/tzinit"// Your other, "regular" imports:import (    "fmt"    "os"    "time"    ...)因此设置TZenv var 将在任何其他包可以访问该包之前发生time。请注意,我import为 单独使用了一个声明tzinit,这是因为许多代码编辑器/IDE 会按字母顺序重新排列您的导入,这将确保导入tzinit将保持第一个导入。一句警告。Spec : Package initialization声明了初始化包的要求和规则,并没有指定处理导入的顺序(唯一保证的是所有引用的包在使用之前都会被递归初始化)。这意味着尽管当前的编译器按照列出的方式处理它们,但您不能 100% 依赖它。还有一个问题,即使是main包也有多个源文件,以不同的顺序向编译器提供它们也可能会改变初始化顺序。该规范将此作为“建议”:为了确保可重现的初始化行为,鼓励构建系统以词法文件名顺序向编译器呈现属于同一包的多个文件。所以为了安全起见,最好TZ在启动 Go 应用程序之前设置环境变量。

墨色风雨

在这里为偶然发现此页面的人添加我的答案。包中有一个全局变量time,像这样使用它main.gopackage mainimport "time"func main() {    loc, err := time.LoadLocation("Africa/Cairo")    // handle err    time.Local = loc // -> this is setting the global timezone}您的系统必须安装时区数据库。在 docker 中,你必须 apt get/apk add tzdata。但是如果你使用的是go1.15,你也可以嵌入时区数据库而无需tzdata在系统上安装。package mainimport (    "time"    _ "time/tzdata")func main() {    loc, err := time.LoadLocation("Africa/Cairo")    // handle err    time.Local = loc // -> this is setting the global timezone}

皈依舞

我可能会迟到,但在全球环境中设置时区并不是一种可靠的方法。它应该在变量或结构中全局设置。下面是在变量中设置时区的示例。也在围棋游乐场package mainimport (    "fmt"    "log"    "time")func main() {    if err := setTimezone("America/Los_Angeles"); err != nil {        log.Fatal(err) // most likely timezone not loaded in Docker OS    }    t := getTime(time.Now())    fmt.Println(t)}var loc *time.Locationfunc setTimezone(tz string) error {    location, err := time.LoadLocation(tz)    if err != nil {        return err    }    loc = location    return nil}func getTime(t time.Time) time.Time {    return t.In(loc)}

SMILET

请注意,如果您想在 AWS 上部署您的应用程序,time.LoadLocation可能会返回错误,因为它找不到数据库文件。从文档:LoadLocation 按顺序在以下位置查找 IANA 时区数据库:由 ZONEINFO 环境变量命名的目录或未压缩的 zip 文件在 Unix 系统上,系统标准安装位置$GOROOT/lib/time/zoneinfo.ziptime/tzdata 包,如果它是导入的您应该导入time/tzdata包来解决问题:import _ "time/tzdata" // Important!func main() {    location, err := time.LoadLocation("Europe/Berlin")    if err != nil {        log.Fatal().Msgf("Err loading location: %v", err)    }    time.Local = location}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go