本文介绍了在狂欢中解析json日期时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从json请求中解析日期时间。请求如下所示:

  {
startedAt:2017-06-01 10:39 ,
...
}

被解码的结构看起来像这:

  type MyStruct struct {
StartedAt time.Time`json:startedAtbson:startedAt`
...
}

解码行如下所示:

  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
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日期时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-20 23:06