74

如何解析 Go 中的非标准日期/时间字符串。例如,如果我想将字符串10/15/1983转换为time.Time? 据说该time.Parse()功能允许您指定格式。

http://play.golang.org/p/v5DbowXt1x

package main

import "fmt"
import "time"

func main() {
    test, err := time.Parse("10/15/1983", "10/15/1983")
    if err != nil {
        panic(err)
    }

    fmt.Println(test)
}

这会导致恐慌。

panic: parsing time "10/15/1983" as "10/15/1983": cannot parse "" as "0/"

从逻辑上讲,这是有道理的,因为它应该如何知道哪一天是哪一个月。

其他语言具有类似于以下的功能:

parse("mm/dd/yyyy", "10/15/1983")

我在 Go 文档中找不到这样的函数,我唯一的选择是正则表达式吗?

4

4 回答 4

169

time.Parse 正在寻找一些关键值。

通过改变:

test, err := time.Parse("10/15/1983", "10/15/1983")

test, err := time.Parse("01/02/2006", "10/15/1983")

解析器会识别它。

这是操场上修改后的代码

package main

import "fmt"
import "time"

func main() {
    test, err := time.Parse("01/02/2006", "10/15/1983")
    if err != nil {
        panic(err)
    }

    fmt.Println(test)
}


您可以利用src/pkg/time/format.go文件中的常量列表来创建自己的解析格式。

const (
    stdLongMonth      = "January"
    stdMonth          = "Jan"
    stdNumMonth       = "1"
    stdZeroMonth      = "01"
    stdLongWeekDay    = "Monday"
    stdWeekDay        = "Mon"
    stdDay            = "2"
    stdUnderDay       = "_2"
    stdZeroDay        = "02"
    stdHour           = "15"
    stdHour12         = "3"
    stdZeroHour12     = "03"
    stdMinute         = "4"
    stdZeroMinute     = "04"
    stdSecond         = "5"
    stdZeroSecond     = "05"
    stdLongYear       = "2006"
    stdYear           = "06"
    stdPM             = "PM"
    stdpm             = "pm"
    stdTZ             = "MST"
    stdISO8601TZ      = "Z0700"  // prints Z for UTC
    stdISO8601ColonTZ = "Z07:00" // prints Z for UTC
    stdNumTZ          = "-0700"  // always numeric
    stdNumShortTZ     = "-07"    // always numeric
    stdNumColonTZ     = "-07:00" // always numeric
)

因此,只要您的格式指定年份,就应该使用“06”或“2006”,秒由“05”或“5”指定,时区指定为“MST”、“Z0700”、“Z07:00” ”、“-0700”、“-07”或“-07:00”。如果您引用常量列表,您可能会将需要解析的任何标准格式放在一起。

例如,如果您想解析通用日志格式(Apache 用于其日志文件的格式)中的日期/时间,您可以通过将以下字符串time.Parse()作为布局参数传递给来实现。

"02/Jan/2006:15:04:05 -0700"

“02”表示月份字段,“Jan”表示月份名称字段,“2006”表示年份字段,“15”表示 24 小时格式的小时字段,“04”表示分钟字段, “05”表示秒字段,“-0700”表示时区字段。

该格式将解析当前 PST 时间:31/Dec/2012:15:32:25 -0800

所以time.Parse()调用看起来像这样:

test, err := time.Parse("02/Jan/2006:15:04:05 -0700", "31/Dec/2012:15:32:25 -0800")
于 2012-12-31T22:36:43.497 回答
7

如果您不记得指定布局中的数字(“2006-01-02T15:04:05.000Z”),您可以使用我的简单日期格式库github.com/metakeule/fmtdate,它使用 MS Excel 约定,如 Y ,M,D,h 并在内部将它们转换为数字格式:

package main

import (
    "github.com/metakeule/fmtdate"

    "fmt"
)

func main() {
    test, err := fmtdate.Parse("MM/DD/YYYY", "10/15/1983")
    if err != nil {
        panic(err)
    }

    fmt.Println(test)
}
于 2015-05-02T08:25:46.253 回答
2

如果您正在寻找 C 风格的格式化函数:在查看了一些选项后,我选择了https://github.com/cactus/gostrftime,因为它通常遵循 strfmt(3) 表示法。

引用这个例子:

import (
    "fmt"
    "time"
    "github.com/cactus/gostrftime"
)

func main() {
    now := time.Now()
    fmt.Println(gostrftime.Format("%Y-%m-%d", now))
}

如果 C 和 Go 都必须使用日期格式并且不触及 C 实现,则别无选择,只能在 Go 端进行调整。上面的包满足了这个需求。

于 2020-01-13T10:10:25.313 回答
0

如果您不想费心记住幻数,可以这样做:

package main

import (
   "fmt"
   "time"
)

func main() {
   var (
      y, d int
      m time.Month
   )
   fmt.Sscanf("10/15/1983", "%v/%v/%v", &m, &d, &y)
   t := time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
   fmt.Println(t) // 1983-10-15 00:00:00 +0000 UTC
}

https://golang.org/pkg/fmt#Sscanf

于 2021-03-27T03:06:13.727 回答