在golang中全局设置时区

时间:2019-01-25 10:32:20

标签: go time

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

我看过 time 包,初始化时区发生在

  

time / zoneinfo_unix.go @ initLocal

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

如果不是,则回退到/etc/localtime;如果不是,则回退到UTC


到目前为止我尝试过的

1-效果很好-但我不想使用任何一种方法-:

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

2-没用

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

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


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

Docker映像:golang:1.11.2

3 个答案:

答案 0 :(得分:4)

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

如何确保?创建一个除了设置时区外不执行其他任何操作的程序包(以后您可以在其中添加其他内容,但是对于我们的示例来说就足够了)。

赞:

package tzinit

import (
    "os"
)

func init() {
    os.Setenv("TZ", "Africa/Cairo")
}

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

package main

import _ "path/to/tzinit"

// Your other, "regular" imports:
import (
    "fmt"
    "os"
    "time"
    ...
)

因此设置TZ环境变量将发生在任何其他程序包可以访问time程序包之前。

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

警告语。

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

  

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

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

答案 1 :(得分:0)

我可能迟到了,但是在全局环境中设置时区并不是一种可靠的方法。 应该在变量或结构中全局设置。以下是在变量中设置的时区的示例。同样在Go Playground

package main

import (
    "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.Location

func setTimezone(tz string) error {
    location, err := time.LoadLocation("America/Los_Angeles")
    if err != nil {
        return err
    }
    loc = location
    return nil
}

func getTime(t time.Time) time.Time {
    return t.In(loc)
}

答案 2 :(得分:0)

在这里为偶然浏览此页面的人添加我的分析服务。 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
}

您的系统必须安装了时区数据库。 在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
}