Go每日一庫之dateparse處理時間
簡介
不管什麼時候,處理時間總是讓人頭疼的一件事情。因為時間格式太多樣化瞭,再加上時區,夏令時,閏秒這些細枝末節處理起來更是困難。所以在程序中,涉及時間的處理我們一般借助於標準庫或第三方提供的時間庫。今天要介紹的dateparse專註於一個很小的時間處理領域——解析日期時間格式的字符串。
快速使用
本文代碼使用 Go Modules。
創建目錄並初始化:
$ mkdir dateparse && cd dateparse $ go mod init github.com/darjun/go-daily-lib/dateparse
安裝dateparse庫:
$ go get -u github.com/araddon/dateparse
使用:
package main import ( "fmt" "log" "github.com/araddon/dateparse" ) func main() { t1, err := dateparse.ParseAny("3/1/2014") if err != nil { log.Fatal(err) } fmt.Println(t1.Format("2006-01-02 15:04:05")) t2, err := dateparse.ParseAny("mm/dd/yyyy") if err != nil { log.Fatal(err) } fmt.Println(t2.Format("2006-01-02 15:04:05")) }
ParseAny()方法接受一個日期時間字符串,解析該字符串,返回time.Time類型的值。如果傳入的字符串dateparse庫無法識別,則返回一個錯誤。上面程序運行輸出:
$ go run main.go
2014-03-01 00:00:00
2021/06/24 14:52:39 Could not find format for “mm/dd/yyyy”
exit status 1
需要註意,當我們寫出”3/1/2014″這個時間的時候,可以解釋為2014年3月1日,也可以解釋為2014年1月3日。這就存在二義性,dateparse默認采用mm/dd/yyyy這種格式,也就是2014年3月1日。我們也可以使用ParseStrict()函數讓這種具有二義性的字符串解析失敗:
func main() { t, err := dateparse.ParseStrict("3/1/2014") if err != nil { log.Fatal(err) } fmt.Println(t.Format("2006-01-02 15:04:05")) }
運行:
$ go run main.go
2021/06/24 14:57:18 This date has ambiguous mm/dd vs dd/mm type format
exit status 1
格式
dateparse支持豐富的日期時間格式,基本囊括瞭所有常用的格式。它支持標準庫time中預定義的所有格式:
// src/time/format.go const ( ANSIC = "Mon Jan _2 15:04:05 2006" UnixDate = "Mon Jan _2 15:04:05 MST 2006" RubyDate = "Mon Jan 02 15:04:05 -0700 2006" RFC822 = "02 Jan 06 15:04 MST" RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone RFC850 = "Monday, 02-Jan-06 15:04:05 MST" RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST" RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone RFC3339 = "2006-01-02T15:04:05Z07:00" RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" Kitchen = "3:04PM" // Handy time stamps. Stamp = "Jan _2 15:04:05" StampMilli = "Jan _2 15:04:05.000" StampMicro = "Jan _2 15:04:05.000000" StampNano = "Jan _2 15:04:05.000000000" )
支持的完整格式查看dateparse README。
時區
dateparse支持在特定時區解析日期時間字符串。我們可以通過調用標準庫的time.LoadLocation()方法,傳入時區標識字符串來獲得時區對象。時區標識字符串是類似Asia/Shanghai,America/Chicago這樣的格式,它表示一個具體的時區,前者上海,後者洛杉磯。調用dateparse.ParseIn()方法傳入時區對象,在指定時區中解析。time包中還預定義瞭兩個時區對象,time.Local表示本地時區,time.UTC表示 UTC 時區。時區的權威數據請看IANA。
func main() { tz1, _ := time.LoadLocation("America/Chicago") t1, _ := dateparse.ParseIn("2021-06-24 15:50:30", tz1) fmt.Println(t1.Local().Format("2006-01-02 15:04:05")) t2, _ := dateparse.ParseIn("2021-06-24 15:50:30", time.Local) fmt.Println(t2.Local().Format("2006-01-02 15:04:05")) }
運行:
$ go run main.go
2021-06-25 04:50:30
2021-06-24 15:50:30
美國洛杉磯時區的”2021年6月24日 15時30分30秒”等於本地時區(北京時間)的”2021年6月25日 04時50分30秒”。
cli
dateparse還提供瞭一個命令行工具,用於極快地查看日期時間格式。安裝:
$ go install github.com/araddon/dateparse/dateparse
默認會安裝在$GOPATH路徑下,我習慣上把$GOPATH/bin放到$PATH中。所以dateparse命令可以直接使用。
dateparse命令接收一個字符串,和一個可選的時區選項:
$ dateparse --timezone="Asia/Shanghai" "2021-06-24 06:46:08" Your Current time.Local zone is CST Layout String: dateparse.ParseFormat() => 2006-01-02 15:04:05 Your Using time.Local set to location=Asia/Shanghai CST +-------------+---------------------------+-------------------------------+-------------------------------------+ | method | Zone Source | Parsed | Parsed: t.In(time.UTC) | +-------------+---------------------------+-------------------------------+-------------------------------------+ | ParseAny | time.Local = nil | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC day=4 | | ParseAny | time.Local = timezone arg | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC day=4 | | ParseAny | time.Local = time.UTC | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC day=4 | | ParseIn | time.Local = nil | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC | | ParseIn | time.Local = timezone arg | 2021-06-24 06:46:08 +0800 CST | 2021-06-23 22:46:08 +0000 UTC | | ParseIn | time.Local = time.UTC | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC | | ParseLocal | time.Local = nil | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC | | ParseLocal | time.Local = timezone arg | 2021-06-24 06:46:08 +0800 CST | 2021-06-23 22:46:08 +0000 UTC | | ParseLocal | time.Local = time.UTC | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC | | ParseStrict | time.Local = nil | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC | | ParseStrict | time.Local = timezone arg | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC | | ParseStrict | time.Local = time.UTC | 2021-06-24 06:46:08 +0000 UTC | 2021-06-24 06:46:08 +0000 UTC | +-------------+---------------------------+-------------------------------+-------------------------------------+
輸出當前本地時區,格式字符串(可用於生成同樣格式的日期時間字符串)和一個表格。表格裡面的數據是分別對ParseAny/ParseIn/ParseLocal/ParseStrict在不同的時區下調用的結果。
method列表示調用的方法,Zone Source列表示將本地時區設置的值,Parsed列是以日期時間字符串調用ParseAny()返回的time.Time對象的Format()方法調用結果,Parsed: t.In(time.UTC)列在返回的time.Time對象調用Format()方法前將其轉為 UTC 時間。
由於ParseAny/ParseStrict不會考慮本地時區,都是在 UTC 下解析字符串,所以這 6 行的最後兩列結果都一樣。
ParseIn的第二行,將time.Local設置為我們通過命令行選項設置的時區,上面我設置為Asia/Shanghai,對應的 UTC 時間相差 8 小時。ParseLocal也是如此。
下面是dateparse命令行的部分源碼,可以對照查看:
func main() { parsers := map[string]parser{ "ParseAny": parseAny, "ParseIn": parseIn, "ParseLocal": parseLocal, "ParseStrict": parseStrict, } for name, parser := range parsers { time.Local = nil table.AddRow(name, "time.Local = nil", parser(datestr, nil, false), parser(datestr, nil, true)) if timezone != "" { time.Local = loc table.AddRow(name, "time.Local = timezone arg", parser(datestr, loc, false), parser(datestr, loc, true)) } time.Local = time.UTC table.AddRow(name, "time.Local = time.UTC", parser(datestr, time.UTC, false), parser(datestr, time.UTC, true)) } } func parseIn(datestr string, loc *time.Location, utc bool) string { t, err := dateparse.ParseIn(datestr, loc) if err != nil { return err.Error() } if utc { return t.In(time.UTC).String() } return t.String() }
註意輸出的本地時區為 CST,它可以代表不同的時區:
Central Standard Time (USA) UT-6:00
Central Standard Time (Australia) UT+9:30
China Standard Time UT+8:00
Cuba Standard Time UT-4:00
CST 可以同時表示美國、澳大利亞、中國和古巴四個國傢的標準時間。
總結
使用dateparse可以很方便地從日期時間字符串中解析出時間對象和格式(layout)。同時dateparse命令行可以快速的查看和轉換相應時區的時間,是一個非常不錯的小工具。
大傢如果發現好玩、好用的 Go 語言庫,歡迎到 Go 每日一庫 GitHub 上提交 issue😄
參考
dateparse GitHub:https://github.com/araddon/dateparse
Go 每日一庫 GitHub:https://github.com/darjun/go-daily-lib
到此這篇關於Go每日一庫之dateparse處理時間的文章就介紹到這瞭,更多相關Go dateparse處理時間內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Go中time.RFC3339 時間格式化的實現
- go語言中time包的各種函數總結
- Go編寫定時器與定時任務詳解(附第三方庫gocron用法)
- mysql8.0 my.ini 如何永久修改時區
- django時區問題的解決