许多新手开发人员在处理时区时感到困惑。
- 如何将它们存储在数据库中
- 如何在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可能的坑
正如标准库文档中所说的:
LoadLocation所需的时区数据库可能并不存在于所有系统上,尤其是非unix系统. 如果有的话,LoadLocation查找由ZONEINFO环境变量命名的目录或未压缩的 ZONEINFO
环境变量命名的zip文件, 然后查找Unix系统上已知的安装位置,最后查找 $GOROOT/lib/time/ ZONEINFO .zip
.
Docker Go语言使用时区
默认的情况下时区信息文件时在Go安装的时候已经存在. 但是万一你部署和编译docker使用的时 multi-stage-docker Alpine 镜像.你可以手动的使用一下命令来添加时区的数据.
这将把时区信息添加到 alpine 镜像的 /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中查看完整示例