激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Golang - Go中時間與時區(qū)問題的深入講解

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

2022-01-21 00:36陳少文 Golang

go語言中如果不設置指定的時區(qū),通過time.Now()獲取到的就是本地時區(qū),下面這篇文章主要給大家介紹了關于Go中時間與時區(qū)問題的相關資料,需要的朋友可以參考下

1. 時間與時區(qū)

1.1 時間標準

UTC,世界標準時間,是現(xiàn)在的時間標準,以原子時計時。

GMT,格林威治時間,是以前的時間標準,規(guī)定太陽每天經(jīng)過位于英國倫敦郊區(qū)的皇家格林威治天文臺的時間為中午 12 點。

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

1.2 時區(qū)劃分

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

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

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

1.3 Local 時間

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

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

2. Go 中的時間及序列化

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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 時間字段的序列化

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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)體中的時間字段序列化

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
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 對時間字段的序列化,通過其提供的擴展指定 key 為 startedat、finishedat 的時間字段,指定序列化時使用 timeFormat := time.RFC1123Z 格式和 locale, _ := time.LoadLocation("Asia/Shanghai") 時區(qū)。

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

3.1 在 Linux 中

執(zhí)行命令:

?
1
timedatectl set-timezone Asia/Shanghai

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

?
1
2
3
TZ='Asia/Shanghai'
 
export TZ

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

3.1 在 Docker 中

在制作鏡像時,直接在 Dockerfile 設置 TZ 變量,可能會碰到問題:

?
1
2
3
4
5
FROM alpine
 
ENV TZ='Asia/Shanghai'
 
COPY ./time.go .

報錯: panic: time: missing Location in call to Time.In

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

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

?
1
2
3
4
5
6
7
8
9
FROM alpine
 
 
 
RUN apk add tzdata && \
 
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
 
    echo "Asia/Shanghai" > /etc/timezone

在運行容器時,可以直接掛載主機的時區(qū)描述文件:

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

3.2 在 Kubernetes 中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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

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

4. 參考

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

5.golang時區(qū)處理

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

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

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

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
       var cstZone = time.FixedZone("CST", -7*3600) //設定要轉(zhuǎn)換的時區(qū)<br>                            <br>                h,:=time.ParseDuration("-1h") //中國的時間是+8區(qū)
 
// element
 
t,err:=time.Parse("2006-01-02 15:04:05",item.SaleStartTime)//要處理的時間格式,使用入的字符串要跟格式化的一致
 
var tString string
 
if err!=nil{
 
       tString=time.Now().In(cstZone).Format("2006-01-02T15:04:05-0700") // 這時有個坑,不需要的自己想加法解決
 
}else{<br>                       t=t.Add(8*h) //要減去+8區(qū)
 
       tString=t.In(cstZone).Format("2006-01-02T15:04:05-0700") // 使用時區(qū)轉(zhuǎn)化為對應國家的時間。小心格式化的時間,填自己想要的格式。
 
}

總結(jié)

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

原文鏈接:https://www.chenshaowen.com/blog/the-tips-of-time-and-tz-in-go.html

延伸 · 閱讀

精彩推薦
  • Golanggolang的httpserver優(yōu)雅重啟方法詳解

    golang的httpserver優(yōu)雅重啟方法詳解

    這篇文章主要給大家介紹了關于golang的httpserver優(yōu)雅重啟的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    helight2992020-05-14
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
  • Golanggolang如何使用struct的tag屬性的詳細介紹

    golang如何使用struct的tag屬性的詳細介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細介紹,從例子說起,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網(wǎng)11352020-05-21
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • GolangGolang通脈之數(shù)據(jù)類型詳情

    Golang通脈之數(shù)據(jù)類型詳情

    這篇文章主要介紹了Golang通脈之數(shù)據(jù)類型,在編程語言中標識符就是定義的具有某種意義的詞,比如變量名、常量名、函數(shù)名等等,Go語言中標識符允許由...

    4272021-11-24
  • GolangGolang中Bit數(shù)組的實現(xiàn)方式

    Golang中Bit數(shù)組的實現(xiàn)方式

    這篇文章主要介紹了Golang中Bit數(shù)組的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
  • Golanggolang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
  • Golanggo日志系統(tǒng)logrus顯示文件和行號的操作

    go日志系統(tǒng)logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統(tǒng)logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
主站蜘蛛池模板: 欧美a∨一区二区三区久久黄 | 日韩在线观看高清 | 99热久草| 538任你躁在线精品视频网站 | aaaaaaa毛片| 久久成人黄色 | 国产成人精品一区二区仙踪林 | 午夜视频久久 | 欧美1区2区在线观看 | 久章草在线视频 | 国产亚洲精品综合一区 | 操嫩草| 99999久久久久久 | 婷婷一区二区三区四区 | 亚洲国产视频网 | 欧美成人一二三区 | 羞羞羞网站 | 久久综合一区 | 最新中文字幕在线视频 | 高清av在线 | 黄色视频一级毛片 | 久久国产不卡 | 精品中文字幕在线播放 | 精品久久久av | 亚洲精品aaaaa | 水多视频在线观看 | 久久最新网址 | 日韩黄在线 | 黄色免费小网站 | 亚洲成人在线视频网站 | 国产三级在线观看a | 成人在线视频精品 | 看一级毛片 | 欧美一级做性受免费大片免费 | 欧美999| 精品亚洲视频在线 | 中国hdxxxx护士爽在线观看 | 免费观看的毛片手机视频 | 91精品国| 黑人三级毛片 | 毛片视频免费播放 |