为了账号安全,请及时绑定邮箱和手机立即绑定

请各位大佬指点!golang time Unmarshal 必须包含时区吗?求老司机指点!

请各位大佬指点!golang time Unmarshal 必须包含时区吗?求老司机指点!

犯罪嫌疑人X 2019-11-03 15:54:48
不包含时区貌似不会成功呢
查看完整描述

2 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

楼上的回答说的很对,不知道题主问题解决了没有。我也测试了一下,随便把一些过程写在这里。
首先,要支持JSON的编解码,就必须要实现两个接口,分别是json.Marshaler(组包)和json.Unmashaler(解包)。
两个接口的定义如下:
typeMarshalerinterface{
MarshalJSON()([]byte,error)
}
typeUnmarshalerinterface{
UnmarshalJSON([]byte)error
}
第一种方案,为什么必须是RFC3339格式。
time.Time已经实现了这两个接口,可以进入到time/time.go找到源码实现。而之所以字段必须是RFC3999,因为time.Time实现的UnmarshalJSON方法就是按这个格式解析的。
time.Time的UnmarshalJSON的源码实现如下:
func(t*Time)UnmarshalJSON(data[]byte)error{
//Ignorenull,likeinthemainJSONpackage.
ifstring(data)=="null"{
returnnil
}
//FractionalsecondsarehandledimplicitlybyParse.
varerrerror
*t,err=Parse(`"`+RFC3339+`"`,string(data))
returnerr
}
非常简单。
关于什么是RFC3999格式,题主可以参考这篇文章,互联网上的日期和时间。
假设,现在需要一个支持自定义格式的时间类型,Go还是非常灵活的,基于time.Time重新定义即可,在这个基础上再实现json.Unmarshaler接口。
typeCTimetime.Time
//UnmarshalJSONisjoson.Unmarshaler
func(ct*CustomTime)UnmarshalJSON(data[]byte)error{
//Ignorenull,likeinthemainJSONpackage.
ifstring(data)=="null"{
returnnil
}
//FractionalsecondsarehandledimplicitlybyParse.
varerrerror
t,_:=time.ParseInLocation(`"2006-01-02T15:04:05"`,string(data),time.Local)
*ct=CustomTime(t)
returnerr
}
和之前的time.Time实现基本一样,只是解析的格式不一样了。这里就可以不包含时区了,因为已经固定时区为time.Local,即按当前时区解析。
如果想做的更灵活点,可以用forrange把每个时间格式测试一下,通过判断Parse返回的err确定是否解析成功。当然,这种方法不推荐。
这种方式的缺点是fmt.Printf打印的时候,时间不够直观,打印的底层的数据,可以自己试下就知道。当然,这应该是可以解决的。
还有另外一种方式,定义一个新的时间类型结构体,里面只有一个time.Time类型成员。
typeCustomTimestruct{
Timetime.Time
}
func(ct*CustomTime)UnmarshalJSON(data[]byte)error{
//Ignorenull,likeinthemainJSONpackage.
ifstring(data)=="null"{
returnnil
}
//FractionalsecondsarehandledimplicitlybyParse.
varerrerror
ct.Time,err=time.ParseInLocation(`"2006-01-02T15:04:05"`,string(data),time.Local)
returnerr
}
代码都差不多。这种方式再使用fmt.Printf打印,效果就好了很多。
                            
查看完整回答
反对 回复 2019-11-03
  • 2 回答
  • 0 关注
  • 311 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信