为了账号安全,请及时绑定邮箱和手机立即绑定

在golang中全局设置时区

在golang中全局设置时区

Go
米脂 2023-06-01 18:12:51
我正在尝试为我的应用程序修改 golang 时区我看了一下时间包,初始化时区发生在时间/zoneinfo_unix.go @initLocal该函数只是尝试读取环境变量TZ,如果有效则加载它如果不是,它会回落/etc/localtime,如果它无效,它会回落到UTC到目前为止我已经尝试过1- 工作正常 - 但我不想使用这些方法中的任何一种 - :在我的 docker 文件中,我将 ENV 传递给容器,TZ = Africa/Cairo进入容器 bash,运行$ export TZ = Africa/Cairo2-没用在我的应用程序初始化中(应用程序初始化在一个单独的包中,正在主导入),我使用 os.SetEnv("TZ", "Africa/Cairo")当我简化 main 并使用 os.SetEnv("TZ", "Africa/Cairo") 而不导入除“os - time”之外的任何其他包时,它按预期工作关于如何使第二种方法起作用的任何想法?Docker 镜像:golang:1.11.2
查看完整描述

4 回答

?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

您可以使用从您的应用程序内部实现您想要的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"

    ...

)

因此设置TZenv var 将在任何其他包可以访问该包之前发生time。


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


一句警告。


Spec : Package initialization声明了初始化包的要求和规则,并没有指定处理导入的顺序(唯一保证的是所有引用的包在使用之前都会被递归初始化)。这意味着尽管当前的编译器按照列出的方式处理它们,但您不能 100% 依赖它。还有一个问题,即使是main包也有多个源文件,以不同的顺序向编译器提供它们也可能会改变初始化顺序。该规范将此作为“建议”:

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


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


查看完整回答
反对 回复 2023-06-01
?
墨色风雨

TA贡献1853条经验 获得超6个赞

在这里为偶然发现此页面的人添加我的答案。包中有一个全局变量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

}


查看完整回答
反对 回复 2023-06-01
?
皈依舞

TA贡献1851条经验 获得超3个赞

我可能会迟到,但在全球环境中设置时区并不是一种可靠的方法。它应该在变量或结构中全局设置。下面是在变量中设置时区的示例。也在围棋游乐场

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(tz)

    if err != nil {

        return err

    }

    loc = location

    return nil

}


func getTime(t time.Time) time.Time {

    return t.In(loc)

}


查看完整回答
反对 回复 2023-06-01
?
SMILET

TA贡献1796条经验 获得超4个赞

请注意,如果您想在 AWS 上部署您的应用程序,time.LoadLocation可能会返回错误,因为它找不到数据库文件。从文档:

LoadLocation 按顺序在以下位置查找 IANA 时区数据库:

  • 由 ZONEINFO 环境变量命名的目录或未压缩的 zip 文件

  • 在 Unix 系统上,系统标准安装位置

  • $GOROOT/lib/time/zoneinfo.zip

  • time/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

}


查看完整回答
反对 回复 2023-06-01
  • 4 回答
  • 0 关注
  • 369 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信