golang標(biāo)準(zhǔn)庫time時(shí)間包的使用
time包
時(shí)間和日期是我們編程中經(jīng)常會(huì)用到的,本文主要介紹了 Go 語言內(nèi)置的 time 包的基本用法。
- time 包提供了一些關(guān)于時(shí)間顯示和測量用的函數(shù)。
- time 包中日歷的計(jì)算采用的是公歷,不考慮潤秒。
Go 語言中使用time.Time類型表示時(shí)間。我們可以通過time.Now函數(shù)獲取當(dāng)前的時(shí)間對(duì)象,然后從時(shí)間對(duì)象中可以獲取到年、月、日、時(shí)、分、秒等信息。
// timeDemo 時(shí)間對(duì)象的年月日時(shí)分秒
func timeDemo() {
now := time.Now() // 獲取當(dāng)前時(shí)間
fmt.Printf("current time:%v\n", now)
year := now.Year() // 年
month := now.Month() // 月
day := now.Day() // 日
hour := now.Hour() // 小時(shí)
minute := now.Minute() // 分鐘
second := now.Second() // 秒
fmt.Println(year, month, day, hour, minute, second)
}
跨時(shí)區(qū)
Go 語言中使用 location 來映射具體的時(shí)區(qū)。時(shí)區(qū)(Time Zone)是根據(jù)世界各國家與地區(qū)不同的經(jīng)度而劃分的時(shí)間定義,全球共分為24個(gè)時(shí)區(qū)。
中國差不多跨5個(gè)時(shí)區(qū)(壯哉我中國,地大物博),為了時(shí)區(qū)的一致,在國內(nèi)通常使用的是北京的時(shí)區(qū)。
下面的示例代碼中使用beijing來表示東八區(qū)8小時(shí)的偏移量,其中time.FixedZone和time.LoadLocation這兩個(gè)函數(shù)則是用來獲取location信息。
// timezoneDemo 時(shí)區(qū)示例
func timezoneDemo() {
// 中國沒有夏令時(shí),使用一個(gè)固定的8小時(shí)的UTC時(shí)差。
// 對(duì)于很多其他國家需要考慮夏令時(shí)。
secondsEastOfUTC := int((8 * time.Hour).Seconds())
// FixedZone 返回始終使用給定區(qū)域名稱和偏移量(UTC 以東秒)的 Location。
beijing := time.FixedZone("Beijing Time", secondsEastOfUTC)
// 如果當(dāng)前系統(tǒng)有時(shí)區(qū)數(shù)據(jù)庫,則可以加載一個(gè)位置得到對(duì)應(yīng)的時(shí)區(qū)
// 例如,加載紐約所在的時(shí)區(qū)
newYork, err := time.LoadLocation("America/New_York") // UTC-05:00
if err != nil {
fmt.Println("load America/New_York location failed", err)
return
}
fmt.Println()
// 加載上海所在的時(shí)區(qū)
//shanghai, err := time.LoadLocation("Asia/Shanghai") // UTC+08:00
// 加載東京所在的時(shí)區(qū)
//tokyo, err := time.LoadLocation("Asia/Tokyo") // UTC+09:00
// 創(chuàng)建時(shí)間對(duì)象需要指定位置。常用的位置是 time.Local(當(dāng)?shù)貢r(shí)間) 和 time.UTC(UTC時(shí)間)。
//timeInLocal := time.Date(2023, 10, 27, 20, 0, 0, 0, time.Local) // 系統(tǒng)本地時(shí)間
timeInUTC := time.Date(2023, 10, 27, 12, 0, 0, 0, time.UTC)
sameTimeInBeijing := time.Date(2023, 10, 27, 20, 0, 0, beijing)
sameTimeInNewYork := time.Date(2009, 1, 1, 7, 0, 0, 0, newYork)
// 北京時(shí)間(東八區(qū))比UTC早8小時(shí),所以上面兩個(gè)時(shí)間看似差了8小時(shí),但表示的是同一個(gè)時(shí)間
timesAreEqual := timeInUTC.Equal(sameTimeInBeijing)
fmt.Println(timesAreEqual)
// 紐約(西五區(qū))比UTC晚5小時(shí),所以上面兩個(gè)時(shí)間看似差了5小時(shí),但表示的是同一個(gè)時(shí)間
timesAreEqual = timeInUTC.Equal(sameTimeInNewYork)
fmt.Println(timesAreEqual)
}
注意由于time.loadLocation 依賴系統(tǒng)的時(shí)區(qū)數(shù)據(jù)庫,在不確定程序的運(yùn)行環(huán)境的情況下建議先定義時(shí)區(qū)偏移量,然后使用time.FixedZone 的方式指定時(shí)區(qū)。
(這個(gè)我遇到過,你們敢信,在這個(gè)時(shí)代,我曾經(jīng)遇到過一個(gè)xp系統(tǒng)的電腦。人還不會(huì)配置時(shí)間,系統(tǒng)時(shí)間就有問題。所以一定不能依賴系統(tǒng)的時(shí)區(qū)數(shù)據(jù)庫)
時(shí)間戳
Unix Time是自1970年1月1日 00:00:00 UTC 至當(dāng)前時(shí)間經(jīng)過的總秒數(shù)。
// timestampDemo 時(shí)間戳
func timestampDemo() {
now := time.Now() // 獲取當(dāng)前時(shí)間
timestamp := now.Unix() // 秒級(jí)時(shí)間戳
milli := now.UnixMilli() // 毫秒時(shí)間戳 Go1.17+
micro := now.UnixMicro() // 微秒時(shí)間戳 Go1.17+
nano := now.UnixNano() // 納秒時(shí)間戳
fmt.Println(timestamp, milli, micro, nano)
}
time 包還提供了一系列將 int64 類型的時(shí)間戳轉(zhuǎn)換為時(shí)間對(duì)象的方法。
這里注意還是得轉(zhuǎn)換一下時(shí)區(qū)
secondsEastOfUTC := int((8 * time.Hour).Seconds())
beijing := time.FixedZone("Beijing Time", secondsEastOfUTC)
// 北京時(shí)間 2022-02-22 22:22:22.000000022 +0800 CST
t := time.Date(2022, 02, 22, 22, 22, 22, 22, beijing)
var (
sec = t.Unix()
msec = t.UnixMilli()
usec = t.UnixMicro()
)
// 將秒級(jí)時(shí)間戳轉(zhuǎn)為時(shí)間對(duì)象(第二個(gè)參數(shù)為不足1秒的納秒數(shù))
timeObj := time.Unix(sec, 22)
fmt.Println(timeObj) // 2022-02-22 22:22:22.000000022 +0800 CST
timeObj = time.UnixMilli(msec) // 毫秒級(jí)時(shí)間戳轉(zhuǎn)為時(shí)間對(duì)象
fmt.Println(timeObj) // 2022-02-22 22:22:22 +0800 CST
timeObj = time.UnixMicro(usec) // 微秒級(jí)時(shí)間戳轉(zhuǎn)為時(shí)間對(duì)象
fmt.Println(timeObj) // 2022-02-22 22:22:22 +0800 CST
時(shí)間間隔
time.Duration是time包定義的一個(gè)類型,它代表兩個(gè)時(shí)間點(diǎn)之間經(jīng)過的時(shí)間,以納秒為單位。
time.Duration表示一段時(shí)間間隔,可表示的最長時(shí)間段大約290年。
time.Duration表示1納秒,time.Second表示1秒。
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
源碼

時(shí)間操作
add
func (t Time) Add(d Duration) Time
func main() {
now := time.Now()
later := now.Add(time.Hour) // 當(dāng)前時(shí)間加1小時(shí)后的時(shí)間
fmt.Println(later)
}
Sub
func (t Time) Sub(u Time) Duration
返回一個(gè)時(shí)間段t-u。
如果結(jié)果超出了Duration可以表示的最大值或最小值,將返回最大值或最小值。
要獲取時(shí)間點(diǎn)t-d(d為Duration),可以使用t.Add(-d)。
Equal
func (t Time) Equal(u Time) bool
判斷兩個(gè)時(shí)間是否相同,會(huì)考慮時(shí)區(qū)的影響,因此不同時(shí)區(qū)標(biāo)準(zhǔn)的時(shí)間也可以正確比較。
這個(gè)方法和用t==u不同,這種方法還會(huì)比較地點(diǎn)和時(shí)區(qū)信息。
Before
func (t Time) Before(u Time) bool
如果t代表的時(shí)間點(diǎn)在u之前,返回真;否則返回假。
After
func (t Time) After(u Time) bool
如果t代表的時(shí)間點(diǎn)在u之后,返回真;否則返回假。
定時(shí)器
使用time.Tick(時(shí)間間隔)來設(shè)置定時(shí)器,定時(shí)器的本質(zhì)上是一個(gè)通道(channel)
func tickDemo() {
ticker := time.Tick(time.Second) //定義一個(gè)1秒間隔的定時(shí)器
for i := range ticker {
fmt.Println(i)//每秒都會(huì)執(zhí)行的任務(wù)
}
}
時(shí)間格式化
time.Format函數(shù)能夠?qū)⒁粋€(gè)時(shí)間對(duì)象格式化輸出為指定布局的文本表示形式,需要注意的是 Go 語言中時(shí)間格式化的布局不是常見的Y-m-d H:M:S,而是使用2023-10-27 15:04:05.000
- 如果想格式化為12小時(shí)格式,需在格式化布局中添加PM。
- 小數(shù)部分想保留指定位數(shù)就寫0,如果想省略末尾可能的0就寫 9。
// formatDemo 時(shí)間格式化
func formatDemo() {
now := time.Now()
// 格式化的模板為 2006-01-02 15:04:05
// 24小時(shí)制
fmt.Println(now.Format("2006-01-02 15:04:05.000 Mon Jan"))
// 12小時(shí)制
fmt.Println(now.Format("2006-01-02 03:04:05.000 PM Mon Jan"))
// 小數(shù)點(diǎn)后寫0,因?yàn)橛?個(gè)0所以格式化輸出的結(jié)果也保留3位小數(shù)
fmt.Println(now.Format("2006/01/02 15:04:05.000")) // 2022/02/27 00:10:42.960
// 小數(shù)點(diǎn)后寫9,會(huì)省略末尾可能出現(xiàn)的0
fmt.Println(now.Format("2006/01/02 15:04:05.999")) // 2022/02/27 00:10:42.96
// 只格式化時(shí)分秒部分
fmt.Println(now.Format("15:04:05"))
// 只格式化日期部分
fmt.Println(now.Format("2006.01.02"))
}

解析字符串格式的時(shí)間
對(duì)于從文本的時(shí)間表示中解析出時(shí)間對(duì)象,time包中提供了time.Parse和time.ParseInLocation兩個(gè)函數(shù)。
其中time.Parse在解析時(shí)不需要額外指定時(shí)區(qū)信息。
// parseDemo 指定時(shí)區(qū)解析時(shí)間
func parseDemo() {
// 在沒有時(shí)區(qū)指示符的情況下,time.Parse 返回UTC時(shí)間
timeObj, err := time.Parse("2006/01/02 15:04:05", "2022/10/05 11:25:20")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(timeObj) // 2022-10-05 11:25:20 +0000 UTC
// 在有時(shí)區(qū)指示符的情況下,time.Parse 返回對(duì)應(yīng)時(shí)區(qū)的時(shí)間表示
// RFC3339 = "2006-01-02T15:04:05Z07:00"
timeObj, err = time.Parse(time.RFC3339, "2023-10-05T11:25:20+08:00")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(timeObj) // 2022-10-05 11:25:20 +0800 CST
}

time.ParseInLocation函數(shù)需要在解析時(shí)額外指定時(shí)區(qū)信息。
func parseDemo() {
now := time.Now()
fmt.Println(now)
// 加載時(shí)區(qū)
loc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
fmt.Println(err)
return
}
// 按照指定時(shí)區(qū)和指定格式解析字符串時(shí)間
timeObj, err := time.ParseInLocation("2006/01/02 15:04:05", "2022/10/05 11:25:20", loc)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(timeObj)
fmt.Println(timeObj.Sub(now))
}

到此這篇關(guān)于golang標(biāo)準(zhǔn)庫time時(shí)間包的使用的文章就介紹到這了,更多相關(guān)golang time標(biāo)準(zhǔn)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go面向?qū)ο蠓绞讲僮鱆SON庫實(shí)現(xiàn)四則運(yùn)算
這篇文章主要為大家介紹了go面向?qū)ο蠓绞讲僮鱆SON庫實(shí)現(xiàn)四則運(yùn)算的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
關(guān)于Go 空結(jié)構(gòu)體的 3 種使用場景
在今天這篇文章要給大家介紹得是Go 語言中幾種常見類型的寬度,并且基于開頭的問題 ”空結(jié)構(gòu)體“ 進(jìn)行了剖析,需要的朋友可以參考一下,希望對(duì)你有所幫助2021-10-10
Golang中的Slice與數(shù)組及區(qū)別詳解
數(shù)組是一種具有固定長度的基本數(shù)據(jù)結(jié)構(gòu),在golang中與C語言一樣數(shù)組一旦創(chuàng)建了它的長度就不允許改變,數(shù)組的空余位置用0填補(bǔ),不允許數(shù)組越界。今天小編通過實(shí)例代碼操作給大家詳細(xì)介紹lang中的Slice與數(shù)組的相關(guān)知識(shí),一起看看吧2020-02-02
使用Golang?Validator包實(shí)現(xiàn)數(shù)據(jù)驗(yàn)證詳解
在開發(fā)過程中,數(shù)據(jù)驗(yàn)證是一個(gè)非常重要的環(huán)節(jié),而golang中的Validator包是一個(gè)非常常用和強(qiáng)大的數(shù)據(jù)驗(yàn)證工具,提供了簡單易用的API和豐富的驗(yàn)證規(guī)則,下面我們就來看看Validator包的具體使用吧2023-12-12
一文總結(jié)Go語言切片核心知識(shí)點(diǎn)和坑
都說Go的切片用起來絲滑得很,Java中的List怎么用,切片就怎么用,作為曾經(jīng)的Java選手,因?yàn)榍衅氖褂貌坏卯?dāng),喜提缺陷若干,本文就給大家總結(jié)一下Go語言切片核心知識(shí)點(diǎn)和坑,需要的朋友可以參考下2023-06-06
go語言實(shí)現(xiàn)字符串與其它類型轉(zhuǎn)換(strconv包)
strconv包是Go語言標(biāo)準(zhǔn)庫的一部分,主要提供字符串與基本數(shù)據(jù)類型之間的轉(zhuǎn)換功能,使用strconv包可以方便地在不同類型之間進(jìn)行轉(zhuǎn)換,滿足日常編程中的需求,感興趣的可以了解一下2024-10-10
Go語言中init函數(shù)特點(diǎn)、用途和注意事項(xiàng)詳解
go語言中有一個(gè)非常神奇的函數(shù)init,它可以在所有程序執(zhí)行開始前被執(zhí)行,并且每個(gè)package下面可以存在多個(gè)init函數(shù),這篇文章主要給大家介紹了關(guān)于Go語言中init函數(shù)特點(diǎn)、用途和注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下2023-07-07
Go 簡單實(shí)現(xiàn)多租戶數(shù)據(jù)庫隔離
本文主要介紹了Go 簡單實(shí)現(xiàn)多租戶數(shù)據(jù)庫隔離,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05

