问题描述
我试图从json请求中解析日期时间。请求如下所示:
{
startedAt:2017-06-01 10:39 ,
...
}
被解码的结构看起来像这:
type MyStruct struct {
StartedAt time.Time`json:startedAtbson:startedAt`
...
}
解码行如下所示:(c.Request.Body).Decode(& MyStruct)
json.NewDecoder Revel返回此错误:
界面转换:错误是* time.ParseError,而不是* errors.Error
根据revel的文档,
内置2006-01-02,2006-01-02 15:04的SQL标准日期时间格式。
在同一个文档中,他们也说你可以附加如下格式:
func init(){
revel。 TimeFormats = append(revel.TimeFormats,01/02/2006)
}
为了验证格式是否在数组中,我试过这个:
$ p $ func init(){
revel.TimeFormats = append(revel.TimeFormats,2016-06-01 12:12)
}
在最后的绝望行为中,我试着用相同的格式提交它,以致revel会返回json时间:
{
startedAt:2017-06-22T12:22:16.265618819-05:00,
...
}
在这一点上,我不知道该怎么办。任何人都可以得到解析日期时间的狂欢?
更新:我尝试了下面的RickyA的解决方案,但现在有解析错误。
解析时间Mon,02 Jan 2006 15:04:05 -0700asMon, 02 Jan 2006 15:04:05 -0700:can not parseMon,02 Jan 2006 15:04:05 -0700asMon
更令人奇怪的是,我实施了一些黑客手段,以便在中间环境中运行。我将请求时间字段更改为一个字符串,并给它一个转换它的ToX函数。这个函数可以工作,但是当它移动到UnmarshalJSON函数中时,它失败了。
另外,我不能确定这是否是一个错误:
$ b $ pre $
func(t * AnyTime)UnmarshalJSON(b [] byte)错误{
fmt.Println(time.RFC1123Z)
fmt.Println(字符串(b))
fmt.Println(reflect.TypeOf(time.RFC1123Z))
fmt.Println(reflect.TypeOf(string(b)))
.. 。
输出:
<$ p $ code> Mon,2006年1月2日15:04:05 -0700
星期一,2006年1月2日15:04:05 -0700
字符串
字符串
请注意,只有一个字符串带有双引号。这让我相信,传递给UnmarshalJSON的字节数组在其字符串中有双引号。
最终更新:所以我很确定双引号是有意的,并且在某种意义上说是有道理的。 UnmarshalJSON从':'传递包含双引号的','的所有内容。我猜测这样做是为了它也可以支持整数和布尔值。我不喜欢这个解决方案,但这是我解决它的方法:
$ b $ pre $ func(t * AnyTime)UnmarshalJSON(b [ ]字节)错误{
var err错误
sTime:=字符串(b)
sTime = strings.TrimSuffix(sTime,\)
sTime = strings.TrimPrefix (sTime,\)
t.Time,err = time.Parse(time.RFC1123Z,sTime)
...
我遇到了同样的问题,最终为 time.Time $创建了一个自定义类型c $ c
$ p $
pre $ $ $
$编码/ json
时间
字符串
gopkg.in/mgo.v2/bson
)
// ANYTIME //
AnyTime接受任何时间格式的解集//
类型AnyTime struct {time.Time}
func(t AnyTime)MarshalJSON()([ ]字节,错误){
return json.Marshal(t.Time)
}
func(t * AnyTime)UnmarshalJSON(b []字节)错误{
err:= json.Unm arshal(b,& t.Time)
if err!= nil {//假设非tz时间输入
bstr:= strings.Trim(string(b),``)
t.Time,err = time.Parse(2006-01-02T15:04:05,bstr)
if err!= nil {
return err // TODO add more formats to try
$ b返回nil
func(t AnyTime)GetBSON()(interface {},error){
return t .Time,nil
}
func(t * AnyTime)SetBSON(raw bson.Raw)error {
var tm time.Time
err:= raw。 Unmarshal(& tm)
if err!= nil {
return err
}
t.Time = tm.UTC()
返回零
}
func(t AnyTime)ToTime()time.Time {
return t.Time
}
用法:
类型MyStruct结构{
StartedAt genericfields。 AnyTime`json:startedAtbson:startedAt`
...
}
您可能需要调整输入文字r time.Parse
有点。
I'm attempting to parse a Datetime in revel from a json request. The request looks something like this:
{
"startedAt": "2017-06-01 10:39",
...
}
The struct it's being decoded into looks like this:
type MyStruct struct {
StartedAt time.Time `json:"startedAt" bson:"startedAt"`
...
}
The decode line looks like this:
json.NewDecoder(c.Request.Body).Decode(&MyStruct)
Revel returns this error:
interface conversion: error is *time.ParseError, not *errors.Error
According to revel's documentation here, https://revel.github.io/manual/parameters.html
The SQL standard date time formats of 2006-01-02, 2006-01-02 15:04 are built in.
In the same document, they also say you can append formats like this:
func init() {
revel.TimeFormats = append(revel.TimeFormats, "01/02/2006")
}
To verify the format was in the array, I tried this:
func init() {
revel.TimeFormats = append(revel.TimeFormats, "2016-06-01 12:12")
}
In a final act of desperation I tried submitting it in the same format that revel will return json times in:
{
"startedAt": "2017-06-22T12:22:16.265618819-05:00",
...
}
At this point I'm not sure where to go with this. Has anyone been able to get revel to parse a Datetime?
Update: I tried RickyA's solution below, but now there is a parsing error.
parsing time ""Mon, 02 Jan 2006 15:04:05 -0700"" as "Mon, 02 Jan 2006 15:04:05 -0700": cannot parse ""Mon, 02 Jan 2006 15:04:05 -0700"" as "Mon"
What's even stranger is that I implemented a bit of a hack to get this working in the interrum. I changed the request time field to a string, and gave it a ToX function which converted it. That function works, but when it's moved into the UnmarshalJSON function it fails.
Also, I can't tell if this is a bug or not:
func (t *AnyTime) UnmarshalJSON(b []byte) error {
fmt.Println(time.RFC1123Z)
fmt.Println(string(b))
fmt.Println(reflect.TypeOf(time.RFC1123Z))
fmt.Println(reflect.TypeOf(string(b)))
...
This outputs this:
Mon, 02 Jan 2006 15:04:05 -0700
"Mon, 02 Jan 2006 15:04:05 -0700"
string
string
Notice that only 1 of the string has double quotes. This is leading me to believe that some how the byte array passed to UnmarshalJSON has double quotes within its string.
Final Update: So I'm pretty sure the double quotes are intentional, and in a way it makes sense. The UnmarshalJSON is passing everything from the ':' through the ',' which includes the double quotes. I'm guessing this is done so that it can also support integers and booleans. I don't like the solution, but this is how I fixed it:
func (t *AnyTime) UnmarshalJSON(b []byte) error {
var err error
sTime := string(b)
sTime = strings.TrimSuffix(sTime, "\"")
sTime = strings.TrimPrefix(sTime, "\"")
t.Time, err = time.Parse(time.RFC1123Z, sTime)
...
I had the same problem and ended up creating a custom type for time.Time
package genericfields
import (
"encoding/json"
"time"
"strings"
"gopkg.in/mgo.v2/bson"
)
// ANYTIME //
// AnyTime accepts any time format for its unmarshaling //
type AnyTime struct{ time.Time }
func (t AnyTime) MarshalJSON() ([]byte, error) {
return json.Marshal(t.Time)
}
func (t *AnyTime) UnmarshalJSON(b []byte) error {
err := json.Unmarshal(b, &t.Time)
if err != nil { //assume non tz time input
bstr := strings.Trim(string(b), `"`)
t.Time, err = time.Parse("2006-01-02T15:04:05", bstr)
if err != nil {
return err //TODO add more formats to try
}
}
return nil
}
func (t AnyTime) GetBSON() (interface{}, error) {
return t.Time, nil
}
func (t *AnyTime) SetBSON(raw bson.Raw) error {
var tm time.Time
err := raw.Unmarshal(&tm)
if err != nil {
return err
}
t.Time = tm.UTC()
return nil
}
func (t AnyTime) ToTime() time.Time {
return t.Time
}
Usage:
type MyStruct struct {
StartedAt genericfields.AnyTime `json:"startedAt" bson:"startedAt"`
...
}
You might need to tweak the input for time.Parse
somewhat.
这篇关于在狂欢中解析json日期时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!