最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go中時(shí)間與時(shí)區(qū)問題的深入講解

 更新時(shí)間:2021年12月09日 10:31:34   作者:陳少文  
go語(yǔ)言中如果不設(shè)置指定的時(shí)區(qū),通過(guò)time.Now()獲取到的就是本地時(shí)區(qū),下面這篇文章主要給大家介紹了關(guān)于Go中時(shí)間與時(shí)區(qū)問題的相關(guān)資料,需要的朋友可以參考下

1. 時(shí)間與時(shí)區(qū)

1.1 時(shí)間標(biāo)準(zhǔn)

UTC,世界標(biāo)準(zhǔn)時(shí)間,是現(xiàn)在的時(shí)間標(biāo)準(zhǔn),以原子時(shí)計(jì)時(shí)。

GMT,格林威治時(shí)間,是以前的時(shí)間標(biāo)準(zhǔn),規(guī)定太陽(yáng)每天經(jīng)過(guò)位于英國(guó)倫敦郊區(qū)的皇家格林威治天文臺(tái)的時(shí)間為中午 12 點(diǎn)。

UTC 時(shí)間更加準(zhǔn)確,但如果對(duì)精度要求不高,可以視兩種標(biāo)準(zhǔn)等同。

1.2 時(shí)區(qū)劃分

從格林威治本初子午線起,經(jīng)度每向東或者向西間隔 15°,就劃分一個(gè)時(shí)區(qū),因此一共有 24 個(gè)時(shí)區(qū),東、西個(gè) 12 個(gè)。

但為了行政上的方便,通常會(huì)將一個(gè)國(guó)家或者一個(gè)省份劃分在一起。下面是幾個(gè) UTC 表示的時(shí)間:

  • UTC-6(CST — 北美中部標(biāo)準(zhǔn)時(shí)間)
  • UTC+9(JST — 日本標(biāo)準(zhǔn)時(shí)間)
  • UTC+8(CT/CST — 中原標(biāo)準(zhǔn)時(shí)間)
  • UTC+5:30(IST — 印度標(biāo)準(zhǔn)時(shí)間)
  • UTC+3(MSK — 莫斯科時(shí)區(qū))

1.3 Local 時(shí)間

Local 時(shí)間為當(dāng)前系統(tǒng)的帶時(shí)區(qū)時(shí)間,可以通過(guò) /etc/localtime 獲取。實(shí)際上 /etc/localtime 是指向 zoneinfo 目錄下的某個(gè)時(shí)區(qū)。下面是 MacOS 上的執(zhí)行結(jié)果,Linux 上的路徑會(huì)不一樣:

ls -al  /etc/localtime

lrwxr-xr-x  1 root  wheel  39 Apr 26  2021 /etc/localtime -> /var/db/timezone/zoneinfo/Asia/Shanghai

2. Go 中的時(shí)間及序列化

2.1 Go 如何初始化時(shí)區(qū)

  1. 查找 TZ 變量獲取時(shí)區(qū)
  2. 如果沒有 TZ,那么使用 /etc/localtime
  3. 如果 TZ="",那么使用 UTC
  4. 當(dāng) TZ=“foo” 或者 TZ=":foo"時(shí),如果 foo 指向的文件將被用于初始化時(shí)區(qū),否則使用 /usr/share/zoneinfo/foo

下面是 Go 實(shí)現(xiàn)的源碼:

tz, ok := syscall.Getenv("TZ")

switch {

case !ok:

	z, err := loadLocation("localtime", []string{"/etc"})

	if err == nil {

		localLoc = *z

		localLoc.name = "Local"

		return

	}

case tz != "":

	if tz[0] == ':' {

		tz = tz[1:]

	}

	if tz != "" && tz[0] == '/' {

		if z, err := loadLocation(tz, []string{""}); err == nil {

			localLoc = *z

			if tz == "/etc/localtime" {

				localLoc.name = "Local"

			} else {

				localLoc.name = tz

			}

			return

		}

	} else if tz != "" && tz != "UTC" {

		if z, err := loadLocation(tz, zoneSources); err == nil {

			localLoc = *z

			return

		}

	}

}

2.2 Go 時(shí)間字段的序列化

在 Go 使用 “encoding/json” 可以對(duì) Time 字段進(jìn)行序列化,使用 Format 可以對(duì)時(shí)間格式進(jìn)行自定義。如下示例:

package main

import (

	"encoding/json"

	"fmt"

	"time"

)

func main(){

	fmt.Println(time.Now())

	var a, _ := json.Marshal(time.Now())

	fmt.Println(string(a))

	a, _ = json.Marshal(time.Now().Format(time.RFC1123))

	fmt.Println(string(a))

	a, _ = json.Marshal(time.Now().Format("06-01-02"))

	fmt.Println(string(a))

}

輸出結(jié)果:

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"

2.3 Go 結(jié)構(gòu)體中的時(shí)間字段序列化

在結(jié)構(gòu)體中,如果直接使用 “encoding/json” 對(duì)結(jié)構(gòu)體進(jìn)行序列化,得到的將會(huì)是這樣的時(shí)間格式: 2021-12-07T17:31:08.811045+08:00。無(wú)法使用 Format 函數(shù)對(duì)時(shí)間格式進(jìn)行控制。

那么,如何控制結(jié)構(gòu)體中的時(shí)間格式呢?請(qǐng)看如下示例:

package main

import (

	"fmt"

	"strings"

	"time"

	"unsafe"

	"encoding/json"

	jsoniter "github.com/json-iterator/go"

)

func main() {

	var json2 = NewJsonTime()

	var d = struct {

		Title string `json:"title"`

		StartedAt time.Time `json:"time"`

	}{

		Title: "this is title",

		StartedAt: time.Now(),

	}

	t1, _ := json.Marshal(d)

	fmt.Println(string(t1))

	t2, _ := json2.Marshal(d)

	fmt.Println(string(t2))

}

func NewJsonTime() jsoniter.API {

	var jt = jsoniter.ConfigCompatibleWithStandardLibrary

	jt.RegisterExtension(&CustomTimeExtension{})

	return jt

}

type CustomTimeExtension struct {

	jsoniter.DummyExtension

}

func (extension *CustomTimeExtension) UpdateStructDescriptor(structDescriptor *jsoniter.StructDescriptor) {

	for _, binding := range structDescriptor.Fields {

		var typeErr error

		var isPtr bool

		name := strings.ToLower(binding.Field.Name())

		if name == "startedat" {

			isPtr = false

		} else if name == "finishedat" {

			isPtr = true

		} else {

			continue

		}

		timeFormat := time.RFC1123Z

		locale, _ := time.LoadLocation("Asia/Shanghai")

		binding.Encoder = &funcEncoder{fun: func(ptr unsafe.Pointer, stream *jsoniter.Stream) {

			if typeErr != nil {

				stream.Error = typeErr

				return

			}

			var tp *time.Time

			if isPtr {

				tpp := (**time.Time)(ptr)

				tp = *(tpp)

			} else {

				tp = (*time.Time)(ptr)

			}

			if tp != nil {

				lt := tp.In(locale)

				str := lt.Format(timeFormat)

				stream.WriteString(str)

			} else {

				stream.Write([]byte("null"))

			}

		}}

		binding.Decoder = &funcDecoder{fun: func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {

			if typeErr != nil {

				iter.Error = typeErr

				return

			}

			str := iter.ReadString()

			var t *time.Time

			if str != "" {

				var err error

				tmp, err := time.ParseInLocation(timeFormat, str, locale)

				if err != nil {

					iter.Error = err

					return

				}

				t = &tmp

			} else {

				t = nil

			}

			if isPtr {

				tpp := (**time.Time)(ptr)

				*tpp = t

			} else {

				tp := (*time.Time)(ptr)

				if tp != nil && t != nil {

					*tp = *t

				}

			}

		}}

	}

}

type funcDecoder struct {

	fun jsoniter.DecoderFunc

}

func (decoder *funcDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {

	decoder.fun(ptr, iter)

}

type funcEncoder struct {

	fun         jsoniter.EncoderFunc

	isEmptyFunc func(ptr unsafe.Pointer) bool

}

func (encoder *funcEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {

	encoder.fun(ptr, stream)

}

func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool {

	if encoder.isEmptyFunc == nil {

		return false

	}

	return encoder.isEmptyFunc(ptr)

}

輸出結(jié)果:

{"title":"this is title","time":"2021-12-07T17:31:08.811045+08:00"}

{"title":"this is title","time":"Tue, 07 Dec 2021 17:31:08 +0800"}

這里主要是使用 “github.com/json-iterator/go” 包控制 Go 對(duì)時(shí)間字段的序列化,通過(guò)其提供的擴(kuò)展指定 key 為 startedat、finishedat 的時(shí)間字段,指定序列化時(shí)使用 timeFormat := time.RFC1123Z 格式和 locale, _ := time.LoadLocation("Asia/Shanghai") 時(shí)區(qū)。

3. 各種環(huán)境下設(shè)置時(shí)區(qū)

3.1 在 Linux 中

執(zhí)行命令:

timedatectl set-timezone Asia/Shanghai

或者設(shè)置 TZ 環(huán)境變量:

TZ='Asia/Shanghai'

export TZ

都可以設(shè)置時(shí)區(qū)。

3.1 在 Docker 中

在制作鏡像時(shí),直接在 Dockerfile 設(shè)置 TZ 變量,可能會(huì)碰到問題:

FROM alpine

ENV TZ='Asia/Shanghai'

COPY ./time.go .

報(bào)錯(cuò): panic: time: missing Location in call to Time.In

原因: 我們常用的 Linux 系統(tǒng),例如 Ubuntu、CentOS,在 /usr/share/zoneinfo/ 目錄下存放了各個(gè)時(shí)區(qū)而 alpine 鏡像沒有。

因此 alpine 鏡像需要安裝一些額外的包。

FROM alpine

 

RUN apk add tzdata && \

    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \

    echo "Asia/Shanghai" > /etc/timezone

在運(yùn)行容器時(shí),可以直接掛載主機(jī)的時(shí)區(qū)描述文件:

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

3.2 在 Kubernetes 中

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

這里將主機(jī)上的時(shí)區(qū)文件掛載到 Pod 中。

4. 參考

https://github.com/json-iterator/go?

5.golang時(shí)區(qū)處理

如果要設(shè)定時(shí)區(qū),那么在使用時(shí)間函數(shù)之前,就要設(shè)定時(shí)區(qū)。

那么問題就來(lái)了,打個(gè)比喻說(shuō)。我想在墨西哥5月6號(hào)12點(diǎn)45分時(shí)開始促銷。而我在中國(guó),那么你要設(shè)定了個(gè)什么樣的數(shù)字呢?

墨西哥是西5時(shí)區(qū)-5,中國(guó)是+8時(shí)區(qū),相差13個(gè)時(shí)區(qū),也就是在中國(guó)今天是5.6號(hào),那么墨西哥是5.5號(hào)

也就是說(shuō),我今天要設(shè)置5.7號(hào)的時(shí)間嗎?

。。。。。。。。。。。。。

其實(shí)我覺得,是不是直接設(shè)定5.6號(hào)就行了。因?yàn)樵O(shè)定了,那么墨西哥是5.6號(hào)做的促銷,你只要在5.7號(hào)跟進(jìn)就行了。

如果你想要看交易數(shù)據(jù)(按照中國(guó)的時(shí)間來(lái)看),那樣才要做轉(zhuǎn)換。也就是中國(guó)時(shí)間5.7號(hào),墨西哥賣出了多少貨。

好了,不扯蛋了。下面是有需要轉(zhuǎn)時(shí)區(qū)的寫法。

       var cstZone = time.FixedZone("CST", -7*3600) //設(shè)定要轉(zhuǎn)換的時(shí)區(qū)<br>                            <br>                h,:=time.ParseDuration("-1h") //中國(guó)的時(shí)間是+8區(qū)

// element

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

var tString string

if err!=nil{

       tString=time.Now().In(cstZone).Format("2006-01-02T15:04:05-0700") // 這時(shí)有個(gè)坑,不需要的自己想加法解決

}else{<br>                       t=t.Add(8*h) //要減去+8區(qū)

       tString=t.In(cstZone).Format("2006-01-02T15:04:05-0700") // 使用時(shí)區(qū)轉(zhuǎn)化為對(duì)應(yīng)國(guó)家的時(shí)間。小心格式化的時(shí)間,填自己想要的格式。

}

總結(jié)

到此這篇關(guān)于Go中時(shí)間與時(shí)區(qū)問題的文章就介紹到這了,更多相關(guān)Go時(shí)間與時(shí)區(qū)問題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文詳解Go語(yǔ)言中對(duì)象池的正確打開方式

    一文詳解Go語(yǔ)言中對(duì)象池的正確打開方式

    對(duì)象池是一種設(shè)計(jì)模式,它維護(hù)一組已經(jīng)創(chuàng)建好的對(duì)象,當(dāng)需要使用對(duì)象時(shí),直接從對(duì)象池中獲取,使用完畢后再放回對(duì)象池,而不是頻繁地創(chuàng)建和銷毀對(duì)象,下面我們就來(lái)看看Go語(yǔ)言中對(duì)象池的具體使用吧
    2025-02-02
  • Go語(yǔ)言中未知異常捕獲的多種場(chǎng)景與實(shí)用技巧

    Go語(yǔ)言中未知異常捕獲的多種場(chǎng)景與實(shí)用技巧

    在Go語(yǔ)言編程中,異常處理是確保程序健壯性的關(guān)鍵環(huán)節(jié),與一些其他編程語(yǔ)言不同,Go沒有傳統(tǒng)的try - catch結(jié)構(gòu)化異常處理機(jī)制,本文將深入探討Go語(yǔ)言中未知異常捕獲的多種場(chǎng)景與實(shí)用技巧,需要的朋友可以參考下
    2024-11-11
  • Golang實(shí)現(xiàn)超時(shí)退出的三種方式

    Golang實(shí)現(xiàn)超時(shí)退出的三種方式

    這篇文章主要介紹了Golang三種方式實(shí)現(xiàn)超時(shí)退出,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • golang的基礎(chǔ)語(yǔ)法和常用開發(fā)工具詳解

    golang的基礎(chǔ)語(yǔ)法和常用開發(fā)工具詳解

    這篇文章主要介紹了golang的基礎(chǔ)語(yǔ)法和常用開發(fā)工具,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Go語(yǔ)言帶緩沖的通道的使用

    Go語(yǔ)言帶緩沖的通道的使用

    Go語(yǔ)言中有緩沖的通道是一種在被接收前能存儲(chǔ)一個(gè)或者多個(gè)值的通道,本文就來(lái)介紹一下Go語(yǔ)言帶緩沖的通道的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Go語(yǔ)言實(shí)戰(zhàn)之詳細(xì)掌握正則表達(dá)式的應(yīng)用與技巧

    Go語(yǔ)言實(shí)戰(zhàn)之詳細(xì)掌握正則表達(dá)式的應(yīng)用與技巧

    正則表達(dá)式是一種從左到右與主題字符串匹配的模式,正則表達(dá)式用于替換字符串中的文本,驗(yàn)證表單,基于模式匹配從字符串中提取子字符串等等,這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言實(shí)戰(zhàn)之詳細(xì)掌握正則表達(dá)式的應(yīng)用與技巧,需要的朋友可以參考下
    2023-12-12
  • 一文詳解Golang的模塊版本管理與語(yǔ)義版本控制

    一文詳解Golang的模塊版本管理與語(yǔ)義版本控制

    在Golang中,模塊(module)是Go 1.11版本引入的依賴管理系統(tǒng),幫助開發(fā)者管理項(xiàng)目的依賴,在Go模塊推出之前,開發(fā)者通常使用GOPATH和vendor目錄來(lái)管理項(xiàng)目的依賴,本文將給大家詳細(xì)介紹Golang的模塊版本管理與語(yǔ)義版本控制,需要的朋友可以參考下
    2023-12-12
  • 夯實(shí)Golang基礎(chǔ)之?dāng)?shù)據(jù)類型梳理匯總

    夯實(shí)Golang基礎(chǔ)之?dāng)?shù)據(jù)類型梳理匯總

    這篇文章主要8為大家介紹了夯實(shí)Golang基礎(chǔ)之?dāng)?shù)據(jù)類型梳理匯總,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2023-10-10
  • Go語(yǔ)言通過(guò)反射實(shí)現(xiàn)獲取各種類型變量的值

    Go語(yǔ)言通過(guò)反射實(shí)現(xiàn)獲取各種類型變量的值

    反射是程序在運(yùn)行期間獲取變量的類型和值、或者執(zhí)行變量的方法的能力,這篇文章主要為大家講講Go語(yǔ)言通過(guò)反射獲取各種類型變量值的方法,需要的可以參考下
    2023-07-07
  • Go標(biāo)準(zhǔn)庫(kù)strconv實(shí)現(xiàn)string類型與其他基本數(shù)據(jù)類型之間轉(zhuǎn)換

    Go標(biāo)準(zhǔn)庫(kù)strconv實(shí)現(xiàn)string類型與其他基本數(shù)據(jù)類型之間轉(zhuǎn)換

    這篇文章主要為大家介紹了Go標(biāo)準(zhǔn)庫(kù)strconv實(shí)現(xiàn)string類型與其他基本數(shù)據(jù)類型之間轉(zhuǎn)換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11

最新評(píng)論

双柏县| 荆门市| 六盘水市| 四会市| 宁陕县| 齐河县| 黄浦区| 同心县| 邮箱| 平湖市| 修武县| 德化县| 宣汉县| 新乡县| 松潘县| 鹰潭市| 白城市| 乌兰察布市| 桦川县| 彩票| 府谷县| 南皮县| 陆良县| 淮阳县| 偃师市| 临朐县| 子洲县| 如皋市| 昭平县| 蕉岭县| 虞城县| 吐鲁番市| 定边县| 瑞昌市| 巧家县| 阳春市| 莫力| 封丘县| 西和县| 嫩江县| 潼南县|