2016-08-27 6 views
3

Hintergrund

I Go lerne und ich versuche, einige JSON Unmarshalling eines Datum zu tun.Abstellungs falsch formatiert Datumzeit in Golang

Ich habe einige JSON von einem Programm erzeugt, schrieb ich in C, ich gebe aus, was ich dachte, war eine gültige ISO8601/RFC3339 Zeitzone Offset. Ich verwende strftime mit folgendem Format string:

%Y-%m-%dT%H:%M:%S.%f%z 

(Beachten Sie, dass %f nicht nativ von strftime unterstützt, ich habe einen Wrapper, der es mit den Nanosekunden ersetzt).

Dies wird dann produzieren folgendes Ergebnis:

2016-08-08T21:35:14.052975+0200 

Unmarshaling dies aber in Go wird nicht funktionieren: https://play.golang.org/p/vzOXbzAwdW

package main 

import (
    "fmt" 
    "time" 
) 

func main() { 
    t, err := time.Parse(time.RFC3339Nano, "2016-08-08T21:35:14.052975+0200") 
    if err != nil { 
     panic(err) 
    } 
    fmt.Println(t) 
} 

Ausgang:

panic: parsing time "2016-08-08T21:35:14.052975+0200" as "2006-01-02T15:04:05.999999999Z07:00": cannot parse "+0200" as "Z07:00" 

(Arbeitsbeispiel: https://play.golang.org/p/5xcM0aHsSw)

Dies ist, weil RFC3339 expects the timezone offset to be in the format 02:00 mit einem :, aber strftime es als 0200 ausgibt.

Also muss ich dies in meinem C-Programm beheben, um das richtige Format auszugeben.

%z  The +hhmm or -hhmm numeric timezone (that is, the hour and 
       minute offset from UTC). (SU) 

Frage

aber jetzt habe ich eine Reihe von JSON-Dateien mit diesem falschen Format:

2016-08-08T21:35:14.052975+0200 

anstelle der richtigen (mit den : in der Zeitzone-Offset):

aber ich möchte immer noch in der Lage sein, es in meinem Go-Programm korrekt zu entpacken. Vorzugsweise sollten zwei verschiedene JSON-Dateien mit nur diesem Unterschied auf die gleiche Weise analysiert werden.

In Bezug auf Marshalling zurück zu JSON sollte das richtige Format verwendet werden.

Dies ist, wie ich definiert habe es in meiner struct:

Time   time.Time `json:"time"` 

Die Frage ist also, was ist die „Go“ auf diese Weise zu tun?

Auch in meinem Codebeispiel verwende ich RFC3339Nano. Wie würde ich das auch in den Metadaten für die Struktur angeben? Wie ich es jetzt mit nur json:"time" habe, ignoriert das die Nano-Sekunden?

+0

Mögliches Duplikat von [json unmarshal time, das nicht im RFC 3339-Format ist] (http://stackoverflow.com/questions/25087960/json-unmarshal-time-that-isnt-in-rfc-3339-format) –

Antwort

10

Sie können Ihre eigenen time Feldtyp definieren, die beide Formate unterstützt:

type MyTime struct { 
    time.Time 
} 

func (self *MyTime) UnmarshalJSON(b []byte) (err error) { 
    s := string(b) 

    // Get rid of the quotes "" around the value. 
    // A second option would be to include them 
    // in the date format string instead, like so below: 
    // time.Parse(`"`+time.RFC3339Nano+`"`, s) 
    s = s[1:len(s)-1] 

    t, err := time.Parse(time.RFC3339Nano, s) 
    if err != nil { 
     t, err = time.Parse("2006-01-02T15:04:05.999999999Z0700", s) 
    } 
    self.Time = t 
    return 
} 

type Test struct { 
    Time MyTime `json:"time"` 
} 

Try on Go Playground

In dem obigen Beispiel wir die vordefinierte nehmen Format time.RFC3339Nano, die wie t definiert ist sein:

RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" 

und das von time.Parse verwendet :

"2006-01-02T15:04:05.999999999Z0700" 

Dieses Zeitformat entfernen ist hier beschrieben: https://golang.org/pkg/time/#pkg-constants

auch die Dokumentation für time.Parse https://golang.org/pkg/time/#Parse

P. S. sehen Die Tatsache, dass das Jahr 2006 in den Zeitformat-Strings verwendet wird, liegt wahrscheinlich daran, dass die erste Version von Golang in diesem Jahr veröffentlicht wurde.

-1

können Sie versuchen, https://play.golang.org/p/IsUpuTKENg

 
package main 

import (
    "fmt" 
    "time" 
) 

func main() { 
    t, err := time.Parse("2006-01-02T15:04:05.999999999Z0700", "2016-08-08T21:35:14.052975-0200") 
    if err != nil { 
     panic(err) 
    } 
    fmt.Println(t) 
} 

Verwandte Themen