前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >这些关于 Golang timezone 时区的坑, 我已经帮你踩过了

这些关于 Golang timezone 时区的坑, 我已经帮你踩过了

原创
作者头像
老麦
发布2023-01-30 13:10:30
8000
发布2023-01-30 13:10:30
举报
文章被收录于专栏:Go与云原生Go与云原生

大家好, 我是老麦, 我将每天 早上9点 为你分享一篇好文章。

Image
Image

这些关于 Golang timezone 时区的坑, 我已经帮你踩过了

原文链接: https://tangx.in/posts/2023/01/09/golang-timezone-issue/

Golang 中一些不太注意的时区问题

1. time/tzdata

Golang 内置的一个时区文件。

  1. 可以在程序中任意位置被导入。导入后, 如果程序 找不到本地 时区文件, 就会使用该库的数据。
    • 本地 指的是 运行环境, 可能是实际的服务器, 也可能是容器。
  2. 通常, 应该在 main.go 中被导入。如果是 库代码不应该 导入该文件。
  3. 导入该文件后, 程序会增加 450KB 大小。
代码语言:javascript
复制
import (
 _ "time/tzdata"
)

在老版本(1.15)以前并不包含时区信息, 通常会在容器化的时候单独处理时区问题。

代码语言:javascript
复制
FROM golang:alpine as build
RUN apk --no-cache add tzdata
WORKDIR /app
ADD . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp

FROM scratch as final
COPY --from=build /app/myapp .
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
ENV TZ=Europe/Berlin
CMD ["/myapp"]

2. time.Parseand time.ParseInLocation

  1. 使用 time.Parse 解析时间, 默认 时区是 UTC
  2. 使用 time.ParseInLocation 解析时间, 可以指定时区
代码语言:javascript
复制
func timeStr2Time() {
 timeStr := "2023-01-09 22:13:17"
 // 返回的是UTC时间 
    // 2023-01-09 22:13:17 +0000 UTC  
 utcTimeObj, err := time.Parse("2006-01-02 15:04:05", timeStr)
 if err == nil {
  fmt.Println("time.Parse", utcTimeObj, utcTimeObj.Unix())
 }

 // 返回的是当地时间 
    // 2023-01-09 22:13:17 +0800 CST
 localTimeObj, err := time.ParseInLocation("2006-01-02 15:04:05", timeStr, time.Local)
 if err == nil {
  fmt.Println("time.ParseLocation", localTimeObj, localTimeObj.Unix())
 }
}

3. 内部时区管理

  1. 默认情况下, 程序使用 程序运行的本地时区
  2. Go提供了两个函数快速转换 时区
    1. time.UTC()
    2. time.Local()
  3. 使用 LoadLocation(name) 设置时区。
  4. 使用 In(loc) 使用时区
代码语言:javascript
复制
func setTimezone() {


 n1.UTC()      // 转换为 UTC 时区
 n1.Local()    // 转换为 本地时区

 n1.Location() // 返回当前时间时区

 // 没怎么用过
 // loc := time.LoadLocationFromTZData()

 loc2, _ := time.LoadLocation("Asia/Shanghai")
 n1 := time.Now().In(loc2)
 fmt.Println(n1)
}

4. 通过代码设置时区

实践操作不允许 通过 代码程序 本身设置时区的。

上面提到的 不允许, 说明

  1. 行为上 可以通过代码设置时区。
  2. 事实上 无法控制结果。

4.1 通过环境变量设置时区

可以通过设置 环境变量 的方式, 设置程序时区。

代码语言:javascript
复制
// $ date # 本地时区 CST
// Mon Jan  9 23:43:03 CST 2023
func setTimezone() {

 os.Setenv("TZ", "UTC")
 fmt.Println(time.Now())
// 2023-01-09 15:42:51.309248 +0000 UTC m=+0.000084251
}

但是, 之后就 再也无法改变 时区了。

代码语言:javascript
复制
func setTimezone() {

 os.Setenv("TZ", "UTC")
 fmt.Println(time.Now())

 os.Setenv("TZ", "Asia/Shanghai")
 fmt.Println(time.Now())
}

// 注意看第二个时间也是 UTC 时间
// 2023-01-09 15:46:41.130211 +0000 UTC m=+0.000180001
// 2023-01-09 15:46:41.130284 +0000 UTC m=+0.000253042

不仅如此, 如果之前执行过时间命令, 那么 即使第一次设置 时区也是无效的。

代码语言:javascript
复制
func setTimezone() {

 fmt.Println(time.Now())

 os.Setenv("TZ", "UTC")
 fmt.Println(time.Now())

}

// 2023-01-09 23:48:52.72857 +0800 CST m=+0.000167418
// 2023-01-09 23:48:52.729103 +0800 CST m=+0.000696960

总结, 时间操作的顺序会 影响 时区的设置。

设置时区

到目前为止, 我还是只能老老实实去 运行环境 中操作, 设置 **环境变量 TZ**。

代码语言:javascript
复制
export TZ=Asia/Shanghai

具体可以参考 在容器中设置时区原来这么简单[1]

除此之外, 还没找到其它好的办法。

参考资料

[1] 在容器中设置时区原来这么简单: https://tangx.in/posts/2022/12/21/docker-container-set-timezone/

互相吹捧, 共同进步

大家好, 我是老麦, 我将每天 早上9点 为你分享一篇好文章。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 这些关于 Golang timezone 时区的坑, 我已经帮你踩过了
    • 1. time/tzdata库
      • 2. time.Parseand time.ParseInLocation
        • 3. 内部时区管理
          • 4. 通过代码设置时区
            • 4.1 通过环境变量设置时区
          • 设置时区
            • 参考资料
          • 互相吹捧, 共同进步
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档