在Golang中全局设置时区

Abd*_*aat 4 time go

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

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

time / zoneinfo_unix.go @ initLocal

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

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


到目前为止我尝试过的

1-工作正常-但我不想使用这些方法之一-:

  • 在我的docker文件中,我将ENV传递给了容器, TZ = Africa/Cairo
  • 进入容器重击,运行 $ export TZ = Africa/Cairo

2-没有工作

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

当我简化主程序并使用os.SetEnv(“ TZ”,“ Africa / Cairo”)而不导入除“ os-time”以外的任何其他软件包时,它可以正常工作


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

Docker镜像:golang:1.11.2

小智 13

在这里为偶然发现此页面的人添加我的分析。包中有一个全局变量,time像这样使用它main.go

package main

import "time"

func main() {
    loc, err := time.LoadLocation("Africa/Cairo")
    // handle err
    time.Local = loc // -> this is setting the global timezone
}
Run Code Online (Sandbox Code Playgroud)

您的系统必须安装时区数据库。在 docker 中,您必须 apt get/apk add tzdata。但是如果你使用的是 go1.15,你也可以嵌入时区数据库而无需tzdata在系统上安装。

package main

import (
    "time"
    _ "time/tzdata"
)

func main() {
    loc, err := time.LoadLocation("Africa/Cairo")
    // handle err
    time.Local = loc // -> this is setting the global timezone
}
Run Code Online (Sandbox Code Playgroud)

  • 但这可能会导致某些“time.*”函数的数据竞争(尽管我更改了“init()”函数中的位置,但有时在测试中我还是会得到它们)。 (3认同)
  • 是的,这可能会导致数据竞争 --> https://github.com/golang/go/issues/34814#issuecomment-540596197 (2认同)

icz*_*cza 8

您可以使用os.Setenv("TZ", "Africa/Cairo"),从应用程序内部实现所需的功能,重要的是必须先调用此功能,然后其他任何程序包才能使用该time程序包中的任何内容。

如何确保?创建一个除了设置时区外什么都不做的包(以后您可以添加其他东西,但是对于我们的示例来说就足够了)。

像这样:

package tzinit

import (
    "os"
)

func init() {
    os.Setenv("TZ", "Africa/Cairo")
}
Run Code Online (Sandbox Code Playgroud)

将此tzinit首先导入到您的main包中,如下所示:

package main

import _ "path/to/tzinit"

// Your other, "regular" imports:
import (
    "fmt"
    "os"
    "time"
    ...
)
Run Code Online (Sandbox Code Playgroud)

因此,设置TZenv var会在其他任何软件包无法访问该time软件包之前进行。

请注意,我import只是为单独使用了一个声明tzinit,其原因是因为许多代码编辑器/ IDE会按字母顺序重新排列导入,这将确保导入tzinit将保持为首次导入。

一句话警告。

规范:程序包初始化”说明了程序包初始化的要求和规则,未指定导入的处理顺序(唯一可以保证的是,所有引用的程序包将在使用前递归初始化)。这意味着,尽管当前的编译器按列出的顺序处理它们,但您不能100%依靠它。还有一个问题,甚至对于main程序包也有多个源文件,以不同的顺序提供给编译器也可能会更改初始化顺序。规范将其作为“建议”:

为了确保可重现的初始化行为,鼓励构建系统以词法文件名的顺序向编译器提供属于同一软件包的多个文件。

因此,为了安全起见,最好是TZ在启动Go应用之前设置环境变量。