简介

不论什么时候,解决工夫总是让人头疼的一件事件。因为工夫格局太多样化了,再加上时区,夏令时,闰秒这些细枝末节解决起来更是艰难。所以在程序中,波及工夫的解决咱们个别借助于规范库或第三方提供的工夫库。明天要介绍的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 mainimport (  "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.go2014-03-01 00:00:002021/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.go2021/06/24 14:57:18 This date has ambiguous mm/dd vs dd/mm type formatexit status 1

格局

dateparse反对丰盛的日期工夫格局,根本囊括了所有罕用的格局。它反对规范库time中预约义的所有格局:

// src/time/format.goconst (  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/ShanghaiAmerica/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.go2021-06-25 04:50:302021-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 CSTLayout String: dateparse.ParseFormat() => 2006-01-02 15:04:05Your 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:00Central Standard Time (Australia) UT+9:30China Standard Time UT+8:00Cuba Standard Time UT-4:00

CST 能够同时示意美国、澳大利亚、中国和古巴四个国家的规范工夫。

总结

应用dateparse能够很不便地从日期工夫字符串中解析出工夫对象和格局(layout)。同时dateparse命令行能够疾速的查看和转换相应时区的工夫,是一个十分不错的小工具。

大家如果发现好玩、好用的 Go 语言库,欢送到 Go 每日一库 GitHub 上提交 issue

参考

  1. dateparse GitHub:github.com/araddon/dateparse
  2. Go 每日一库 GitHub:https://github.com/darjun/go-daily-lib

我的博客:https://darjun.github.io

欢送关注我的微信公众号【GoUpUp】,独特学习,一起提高~