专栏首页landv[golang]在Go中处理时区

[golang]在Go中处理时区

 许多新手开发人员在处理时区时感到困惑。

  • 如何将它们存储在数据库中
  • 如何在Go中解析它们

当将时区存储在数据库中时,请始终遵循一个标准时区,理想的做法是保存UTC时间,并在显示时区时根据需要将其转化为各种时区。

以MYSQL作为存储时间的示例

以下解决方案与DB无关。根据MySQL文档,有两种可以在MySQL存储时间的方法。

  • DATETIME--DATETIME类型用于包含日期和时间部分的值。MYSQL检索DATETIME并以'YYYY-MM-DD hh:mm:ss'格式显示值。支持的范围是'1000-01-01 00:00:00''9999-12-31 23:59:59'
  • TIMESTAMP-TIMESTAMP数据类型用于同时包含日期和时间部分的值。UTC TIMESTAMP的范围是UTC。'1970-01-01 00:00:01''2038-01-19 03:14:07'。

在本文中,我将使用DATETIME为例。

现在,另一个也是最重要的事情是读取并将其转化为其他时区。

Go时间时区的转换

下面的代码是展示我们如何在Go语言中做时区的转换. 首先让我们来定义地区和时区的的字典. 时区列表IANA时区标识可以从这里得到Time Zones,

package main

import (
    "fmt"
    "errors"
    "time"
)

type Country string

const (
    Germany Country = "Germany"
    UnitedStates Country  = "United States"
    China Country = "China"

)

// timeZoneID 是国家=>IANA 标准时区标识符 的键值对字典
var timeZoneID = map[Country]string{
    Germany:      "Europe/Berlin",
    UnitedStates: "America/Los_Angeles",
    China:   "Asia/Shanghai",
}

//获取 IANA 时区标识符
func (c Country) TimeZoneID() (string, error) {
    if id, ok := timeZoneID[c]; ok {
        return id, nil
    }
    return "", errors.New("timezone id not found for country")
}

// 获取tz时区标识符的格式化时间字符
func TimeIn(t time.Time, tz, format string) string {
    
    // https:/golang.org/pkg/time/#LoadLocation loads location on
    // 加载时区
    loc, err := time.LoadLocation(tz)
    if err != nil {
        //handle error
    }
    // 获取指定时区的格式化时间字符串
    return t.In(loc).Format(format)
}

func main() {
    // 获取美国的时区结构体
    tz, err := UnitedStates.TimeZoneID()
    if err != nil {
        //handle error
    }
    //格式化成美国的时区
    usTime := TimeIn(time.Now(), tz, time.RFC3339)

    fmt.Printf("Time in %s: %s",
        UnitedStates,
        usTime,
    )
}

Go语言time.LoadLocation可能的坑

正如标准库文档中所说的:

The time zone database needed by LoadLocation may not be present on all systems, especially non-Unix systems. LoadLocation looks in the directory or uncompressed zip file named by the ZONEINFO environment variable, if any, then looks in known installation locations on Unix systems, and finally looks in $GOROOT/lib/time/zoneinfo.zip.

LoadLocation所需的时区数据库可能并不存在于所有系统上,尤其是非unix系统. 如果有的话,LoadLocation查找由ZONEINFO环境变量命名的目录或未压缩的 ZONEINFO 环境变量命名的zip文件, 然后查找Unix系统上已知的安装位置,最后查找 $GOROOT/lib/time/ ZONEINFO .zip.

Docker Go语言使用时区

默认的情况下时区信息文件时在Go安装的时候已经存在. 但是万一你部署和编译docker使用的时 multi-stage-docker Alpine 镜像.你可以手动的使用一下命令来添加时区的数据.

RUN apk add tzdata

这将把时区信息添加到 alpine 镜像的 /usr/share/timezone. 但是也不要忘记设置环境变量 ZONEINFO 的值为 /usr/share/timezone

ZONEINFO=/usr/share/timezone

这里有一个参考的示例 Dockerfile

FROM golang:1.12-alpine as build_base
RUN apk add --update bash make git
WORKDIR /go/src/github.com/your_repo/your_app/
ENv GO111MODULE on
COPY go.mod .
COPY go.sum .
RUN go mod download

FROM build_bash AS server_builder
COPY . ./
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/your_app

FROM alpine
RUN apk add tzdata

# 自定义运行阶段的命令

示例

您可以在Go playground https://play.golang.org/p/UCKSpIWmiX7中查看完整示例

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [医疗信息化][DICOM教程]DICOM标准简介

    DICOM是一种医疗保健标准,负责管理医学成像的几乎所有方面,例如图像传输,图像解释,打印管理,程序管理和离线存储,并且几乎用于与医疗保健相关的所有成像“模态”...

    landv
  • Vue与REACT两个框架的区别和优势对比

    VUE和REACT两个JavaScript框架都是当下比较受欢迎的,他们两者之间的区别有那些,各自的优缺点是什么,本文将为你呈现。

    landv
  • 元素渲染

    与浏览器的DOM元素不同,REACT元素是创建开销极小的普通对象。REACT DOM会负责更新DOM来与REACT元素保持一致。

    landv
  • Gmail 设置,时区

      我们工作的时候,需要和不同时区的人进行合作。我们需要注意时区问题。如果没有设置好时区,会造成很多不便。

    xuyaowen
  • 数据库表插入时间不对

    使用SpringBoot框架插入时间时,发现时间减少了14个小时,通过日志输出发现错误并不在sql语句,也就是我的插入的时间并没有错,疑惑的是到数据库表里就时间...

    乐心湖
  • 0475-如何统一Hue和Oozie的时区

    在前面的文章中,Fayson介绍过《如何修改Cloudera Manager的时区》,《如何修改Hue的时区》和《如何修改CDSW会话的时区》。在使用Hue创建...

    Fayson
  • NUCLEO-L432KC实现UART1、UART2双串口数据通信(STM32L432KC)

    本博文将简要讲述STM32CubeMX 新建双串口项目工程的过程,具体步骤参见:STM32控制LED灯闪烁(NB-IoT项目实战专栏—4)。

    不脱发的程序猿
  • Spring多数据源配置系列(一)——多数据源配置

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    逝兮诚
  • 许家印砸1000亿布局AI、量子计算等领域,但在科技圈只能算轻壕

    一年半前,万达网科在一支豪华高管团队的护航下出发。本月初,这个“烧钱”的业务被发现已不再是万达四大集团之一。

    量子位
  • SAP Commerce的Content Page,Content Slot和Component在Spartacus里的应用

    按照这篇文章SAP Spartacus的自定义路由里介绍的方式,在SAP Spartacus里创建自定义路由,使用如下url访问:

    Jerry Wang

扫码关注云+社区

领取腾讯云代金券