默认RFC 3339
在Go中,解析json的时间格式默认是RFC 3339,一般情况下 struct 转 json,或 json 转回 struct都没有问题。
type Data struct {
Name string `json:"name"`
Started time.Time `json:"started"`
}
var jsonStr = []byte(`
{
"name": "new year",
"started": "2021-01-01T00:00:00.000+08:00"
}`)
func main() {
var data Data
if err := json.Unmarshal(jsonStr, &data); err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", data)
}
Z,T
上述代码中,日期和时间使用T
分隔开,其实 RFC 3339规范中允许使用空格分隔,目前Go的time包还是使用T
分隔。
+8:00则表示时区,如果不想使用时区,可以使用Z
代替:2021-01-01T00:00:00.000Z
。
还有一点需要注意的是,在Go中,RFC 3339的定义是:
RFC3339 = "2006-01-02T15:04:05Z07:00"
但是如果这样写,却不行。
t, err := time.Parse(time.RFC3339, time.RFC3339)
if err != nil {
log.Fatal(err)
}
fmt.Println(t)
会报错:”parsing time “2006-01-02T15:04:05Z07:00”: extra text: 07:00”。
但是如果是把上述json的时间值修改成2021-01-01T00:00:00.000Z
就没有问题。
格式
默认的时间格式是RFC 3339,如果想换成其他格式,需要自己实现。
先看一下时间格式的定义
一般情况下格式化时间可以这样做:
t, err := time.Parse("2006-01-02", "2021-01-01")
但是如果想从json中解析成不同格式,需要自己实现json.Unmarshaler
接口。
type MyTime struct {
time.Time
}
const layout = "2006-01-02"
func (ct *MyTime) UnmarshalJSON(b []byte) (err error) {
s := strings.Trim(string(b), "\"")
if s == "null" {
ct.Time = time.Time{}
return
}
ct.Time, err = time.Parse(layout, s)
return
}
然后,就可以使用自己的时间类型了。
type Data struct {
Name string `json:"name"`
Started MyTime `json:"started"`
}
var jsonStr = []byte(`
{
"name": "new year",
"started": "2021-01-01"
}`)
func main() {
var data Data
if err := json.Unmarshal(jsonStr, &data); err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", data)
}