Golang empty解析时间时Mac OSX上的位置

时间:2016-08-23 00:40:05

标签: json macos serialization go time

(编辑/更新):感谢@djd指出我们可以跳过所有JSON / struct解码业务;关键问题在于time.Parse

同样的问题出现在这里,Location是“空”而不是UTC(我希望UTC基于文档:https://golang.org/pkg/time/#Parse

“如果没有时区指示符,Parse将返回UTC时间。”

以下是示例代码:https://play.golang.org/p/pb3eMbjSmv

package main

import (
    "fmt"
    "time"
)

func main() {
    // Ignoring the err just for this example's sake!
    parsed, _ := time.Parse(time.RFC3339, "2017-08-15T22:30:00+00:00")
    fmt.Printf("String(): %v\n", parsed.String())
    fmt.Printf("Location(): %v\n", parsed.Location())
}

输出

String(): 2017-08-15 22:30:00 +0000 +0000
Location():

因此,虽然time.Time的{​​{1}}的偏移量似乎是正确的,但其时区名称只是一个空字符串。在其他机器(和The Go Playground)上运行会给出预期的“UTC”位置。

[原帖]:

在我的本地OS X计算机上将时间戳字段从JSON解码为Location时,struct字段的Location为“空”而不是UTC。这对我在本地运行单元测试是有问题的(在time.Time正确设置为UTC的CI服务器上。)

当我在我的机器上运行时,我看到了

Location

因此,虽然go run main.go TimeField.String(): 2017-08-15 22:30:00 +0000 +0000 TimeField.Location(): 的{​​{1}}的偏移量似乎是正确的,但其时区名称只是一个空字符串。这是使用Go 1.5:

time.Time

3 个答案:

答案 0 :(得分:0)

我在Mac上使用我当前的设置发现了相同的行为,我怀疑它在Linux上会有相同的行为(不确定)

$ go version
go version devel +31ad583 Wed Aug 10 19:44:08 2016 +0000 darwin/amd64

为了使其更具确定性,我建议使用自定义的json Unmarshal:

package main

import (
  "encoding/json"
  "fmt"
  "strings"
  "time"
)

type Time struct {
   *time.Time
}

func (t *Time) UnmarshalJSON(b []byte) error {
  const format = "\"2006-01-02T15:04:05+00:00\""
  t_, err := time.Parse(format, string(b))
  if err != nil {
      return err
  }
  *t = Time{&t_}
  return nil
}

type Example struct {
  TimeField *Time `json:"time_field"`
}

func main() {
  inString := "{\"time_field\": \"2017-08-15T22:30:00+00:00\"}"
  var ex Example
  decoder := json.NewDecoder(strings.NewReader(inString))
  decoder.Decode(&ex)
  fmt.Printf("TimeField.String(): %v\n", ex.TimeField.String())
  fmt.Printf("TimeField.Location(): %v\n", ex.TimeField.Location())
}

答案 1 :(得分:0)

是的,你是对的。在The Go Playground中,Local在该沙箱中设置为UTC
The Go Playground

上试用这个有效的示例代码
package main

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
    fmt.Println(runtime.Version(), runtime.GOARCH, runtime.GOOS) //go1.7 amd64p32 nacl

    parsed, err := time.Parse(time.RFC3339, "2017-08-15T22:30:00+00:00")
    if err != nil {
        panic(err)
    }
    fmt.Printf("String(): %v\n", parsed.String())
    fmt.Printf("Location(): %v\n", parsed.Location())
}
The Go Playground上的

输出:

go1.7 amd64p32 nacl
String(): 2017-08-15 22:30:00 +0000 UTC
Location(): UTC 

在本地系统上尝试,输出Location()为空。

您可以将utc := parsed.UTC()的位置设置为UTC,例如此工作示例代码 The Go Playground

package main

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
    fmt.Println(runtime.Version(), runtime.GOARCH, runtime.GOOS) //go1.7 amd64p32 nacl

    parsed, err := time.Parse(time.RFC3339, "2017-08-15T22:30:00+00:00")
    if err != nil {
        panic(err)
    }
    fmt.Printf("String(): %v\n", parsed.String())
    fmt.Printf("Location(): %v\n", parsed.Location())
    utc := parsed.UTC()
    fmt.Printf("String(): %v\n", utc.String())
    fmt.Printf("Location(): %v\n", utc.Location())
}

此外,您可以使用time.ParseInLocation(time.RFC3339, "2017-08-15T22:30:00+00:00", time.UTC),例如此工作示例代码:

package main

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
    fmt.Println(runtime.Version(), runtime.GOARCH, runtime.GOOS) //go1.7 amd64p32 nacl

    parsed, err := time.ParseInLocation(time.RFC3339, "2017-08-15T22:30:00+00:00", time.UTC)
    if err != nil {
        panic(err)
    }
    fmt.Printf("String(): %v\n", parsed.String())
    fmt.Printf("Location(): %v\n", parsed.Location())
}

因此Location()将为UTC

答案 2 :(得分:0)

感谢@djd指出我们可以跳过所有的JSON/struct解码业务;关键问题在于 time.Parse

这里出现了同样的问题,其中 Location 是“空”而不是 UTC(根据文档,我期望 UTC:https://golang.org/pkg/time/#Parse

<块引用>

在没有时区指示器的情况下,Parse 返回一个 UTC 时间。


此答案取自 revision 6 的问题。