如何解析Go中的时间,而不以秒和毫秒为间隔?

如何解析Go中的时间,而不以秒和毫秒为间隔?,go,Go,我必须解析以下格式的时间: 20060102150405000 例如,“20170116111621978”代表2017年1月16日11:16:21.978。在我看来,Go time软件包需要在日期格式(05.000)中嵌入一个句点(因此需要输入)。除了重写源字符串以包含一个句点来用time.parse解析这些字符串之外,我想不出任何方法。有人有什么建议吗?不幸的是,软件包要求布局中的分数秒部分(毫秒)有一个句点前缀,因此您有两个选择: 修改输入以插入句点,这样您就可以使用布局2006010

我必须解析以下格式的时间:

20060102150405000
例如,“20170116111621978”代表2017年1月16日11:16:21.978。在我看来,Go time软件包需要在日期格式(05.000)中嵌入一个句点(因此需要输入)。除了重写源字符串以包含一个句点来用
time.parse解析这些字符串之外,我想不出任何方法。有人有什么建议吗?

不幸的是,软件包要求布局中的分数秒部分(毫秒)有一个句点前缀,因此您有两个选择:

  • 修改输入以插入句点,这样您就可以使用布局
    20060102150405.000
  • 或者切掉最后3位数字,使用布局解析前缀
    20060102150405
    ,解析毫秒(例如使用),并将其添加到时间使用中

似乎无法用标准的Go-parse格式实现这一点

解析日期而不出错的一个技巧是将最后三毫秒的精确数字
time.parse(“20060102150405”+t[len(t)-3:],t)
添加到格式中(最长为秒),但这只能确保解析不会返回错误。它将失去小数部分

此代码段()说明了作者的建议:

package main

import (
    "fmt"
    "time"
    "strconv"
)

const t = "20170116111621978"

func main() {

    dateStr := t[:len(t)-3]
    millisStr := t[len(t)-3:]
    parsed, err := time.Parse("20060102150405", dateStr)
    if err != nil {
        panic(err)
    }
    millis, _ := strconv.Atoi(millisStr)
    parsed = parsed.Add(time.Duration(millis)*time.Millisecond)
    
    // prints true
    fmt.Println(parsed.UnixNano() == time.Date(2017, 1, 16, 11, 16, 21, 978000000, time.UTC).UnixNano())
}

Icza的答案似乎比Steven Penny的答案更有效:

$ go test -bench=. ./parsedate_test.go -benchtime=10s
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i7-7660U CPU @ 2.50GHz
BenchmarkParseMillisSscanf-4         5538606          2159 ns/op         144 B/op         16 allocs/op
BenchmarkParseMillisAddTime-4       74758664           157.4 ns/op         0 B/op          0 allocs/op
PASS
ok      command-line-arguments  26.086s
这似乎可以做到:

package main

import (
   "fmt"
   "time"
)

func main() {
   var (
      year, day, hour, min, sec, mil int
      mon time.Month
   )
   fmt.Sscanf(
      "20060102150405000", "%4v%2v%2v%2v%2v%2v%3v",
      &year, &mon, &day, &hour, &min, &sec, &mil,
   )
   t := time.Date(year, mon, day, hour, min, sec, mil * 1e6, time.UTC)
   fmt.Println(t) // 2006-01-02 15:04:05 +0000 UTC
}

参考下表:我不得不说,我很难从给出的三个(目前)答案中选择一个明确的答案。这三个问题,作为一个整体,实际上是对这个问题的一个好的、全面的回答。我向贡献者表示歉意,我只能选择一个。此解决方案的另一个缺点是它也“接受”无效输入,例如,如果年份为负。
time.Parse()
函数将为该输入报告一个错误。@StevenPenny Negative year只是一个例子
time.Parse()
有更多的验证规则。这个问题的范围是解析一个时间,所以它在范围之内。@icza,它在我回答的范围之外。我不想把它扩大到现在的程度。