Go中時間與時區問題的深入講解

2022-09-22 00:33:08 字數 4648 閱讀 4938

目錄

utc,世界標準時間,是現在的時間標準,以原子時計時。

gmt,格林威治時間,是以前的時間標準,規定太陽每天經過位於英國倫敦郊區的皇家格林威治天文台的時間為中午 12 點。

utc 時間更加準確,但如果對精度要求不高,可以視兩種標準等同。

從格林威治本初子午線起,經度每向東或者向西間隔 15,就劃分乙個時區,因此一共有 24 個時區,東、西個 12 個。

但為了行政上的方便,通常會將乙個國家或者乙個省份劃分在一起。下面是幾個 utc 表示的時間:

local 時間為當前系統的帶時區時間,可以通過 /etc/localtime 獲取。實際上 /etc/localtime 是指向 zoneinfo 目錄下的某個時區。下面是 macos 上的執行結果,linux 上的路徑會不一樣:

ls -al /etc/localtime

lrwxr-xr-x 1 root wheel 39 apr 26 2021 /etc/localtime -> /var/db/timezone/zoneinfo/asia/shanghai

下面是 go 實現的原始碼:

tz, ok := syscall.getenv("tz")

switch )

if err == nil

case tz != "":

if tz[0] == ':'

if tz != "" && tz[0] == '/' ); err == nil else

return

} } else if tz != "" && tz != "utc"

}}在 go 使用 「encoding/json」 可以對 time 字段進行序列化,使用 format 可以對時間格式進行自定義。如下示例:

package程式設計客棧 main

import (

"encoding/json"

"fmt"

"time"

)func main()

輸出結果:

2021-12-07 16:44:44.874809 +0800 cst m=+0.000070010

"2021-12-07t16:44:44.874937+08:00"

"tue, 07 dec 2021 16:44:44 cst"

"00-120-74 16:44:07"

"21-12-07"

在結構體中,如果直接使用 「encoding/json」 對結構體進行序列化,得到的將會是這樣的時間格式: 2021-12-07t17:31:08.811045+08:00。無法使用 format 函式對時間格式進行控制。

那麼,如何控制結構體中的時間格式呢?請看如下示例:

if tp != nil els程式設計客棧e

}}binding.decoder = &funcdecoder

str := iter.readstring()

var t *time.time

if str != ""

t = &tmp

} else

if isptr else

程式設計客棧

}}} }}

type funcdecoder struct

func (decoder *funcdecoder) decode(ptr unsafe.pointer, iter *jsoniter.iterator)

type funcencoder struct

func (encoder *funcencoder) encode(ptr unsafe.pointer, stream *jsoniter.stream)

func (encoder *funcencoder) isempty(ptr unsafe.pointer) bool

return encoder.isemptyfunc(ptr)

}輸出結果:

這裡主要是使用 「github.com/json-iterator/go」 包控制 go 對時間欄位的序列化,通過其提供的擴充套件指定 key 為 startedat、finishedat 的時間字段,指定序列化時使用 timeformat := time.rfc1123z 格式和 locale, _ := time.loadlocation("asia/shanghai") 時區。

執行命令:

timedatectl set-timezone asia/shanghai

或者設定 tz 環境變數:

tz='asia/shanghai'

export t

都可以設定時區。

在製作映象時,直接在 dockerfile 設定 tz 變數,可能會碰到問題:

from alpine

env tz='asia/shanghai'

copy ./time.go .

報錯: panic: time: missing location in call to time.in

原因: 我們常用的 linux 系統,例如 ubuntu、centos,在 /usr/share/zoneinfo/ 目錄下存放了各個時區而 alpine 映象沒有。

因此 alpine 映象需要安裝一些額外的包。

from alpine

run apk add tzdata && \

cp /usr/share/zoneinfo/asia/shanghai /etc/localtime && \

echo "asia/shanghai" > /etc/timezone

在執行容器時,可以直接掛載主機的時區描述檔案:

docker run -it --rm -v /etc/localtime:/etc/localtime:ro nginx

apiversion: v1

kind: pod

metadata:

name: test

namespace: default

spec:

restartpolicy: onfailure

containers:

- name: nginx

image: nginx-test

imagepullpolicy: ifnotpresent

volumemounts:

- name: date-config

mountpath: /etc/localtime

command: ["sleep", "60000"]

volumes:

- name: date-config

hostpath:

path: /etc/localtime

這裡將主機上的時區檔案掛載到 pod 中。

如果要設定時區,那麼在使用時間函式之前,就要設定時區。

那麼問題就來了,打個比喻說。我想在墨西哥5月6號12點45分時開始**。而我在中國,那麼你要設定了個什麼樣的數字呢?

墨西哥是西5時區-5,中國是+8時區,相差13個時區,也就是在中國今天是5.6號,那麼墨西哥是5.5號

也就是說,我今天要設定5.7號的時間嗎?

其實我覺得,是不是直接設定5.6號就行了。因為設定了,那麼墨西哥是5.6號做的**,你只要在5.7號跟進就行了。

如果你想要看交易資料(按照中國的時間來看),那樣才要做轉換。也就是中國時間5.7號,墨西哥賣出了多少貨。

好了,不扯蛋了。下面是有需要轉時區的寫法。

var cstzone = time.fixedzone("cst", -7*3600) //設定要轉換的時區

h,:=time.parseduration("-1h") //中國的時間是+8區

// element

t,err:=time.parse("2006-01-02 15:04:05",item.salestarttime)//要處理的時間格式,使用入的字串要跟格式化的一致

var tstring string

if err!=nilelse

MySQL 時間戳與時區問題

對於使用 timestamp 的場景,mysql 在訪問 timestamp 字段時會做時區轉換,當 time zone 設定為 system 時,mysql 訪問每一行的 timestamp 欄位時,都會通過 libc 的時區函式,獲取 linux 設定的時區,在這個函式中會持有mutex,當大量...

Debian 中的時區與時間設定

轉貼 debian下設定時區的命令是tzconfig。linux 在每次啟動時會載入bios的時間,並在退出時把時間寫回bios。預設情況下,linux認為bios裡的時間是世界時間 utc 因此它讀入世界時間然後根據使用者所在時區計算出本地時間。對於中國而言,就是加上8小時。這種機制在多系統環境中...

深入講解Go語言中函式new與make的使用和區別

前言 本文主要給大家介紹了go語言中函式new與make的使用和區別,關於go語言中new和make是內建的兩個函式,主要用來建立分配型別記憶體。在我們定義生成變數的時候,可能會覺得有點迷惑,其實他們的規則很簡單,下面我們就通過一些示例說明他們的區別和使用,話不多說了,來一起看看詳細的介紹吧。變數的...