2013-06-25 12 views
11

Ho dati XML che sto recuperando tramite una API REST che sono unmarshaling in una struttura GO. Uno dei campi è un campo data, tuttavia il formato data restituito dall'API non corrisponde all'ora predefinita. Il formato di analisi del tempo e quindi l'unmarshal non riesce.Golang XML Unmarshal e time.Time fields

C'è un modo per specificare la funzione unmarshal quale formato di data utilizzare nell'ora. L'analisi del tempo? Mi piacerebbe utilizzare tipi definiti correttamente e utilizzare una stringa per mantenere un campo datetime si sente sbagliato.

Esempio struct:

type Transaction struct { 

    Id int64 `xml:"sequencenumber"` 
    ReferenceNumber string `xml:"ourref"` 
    Description string `xml:"description"` 
    Type string `xml:"type"` 
    CustomerID string `xml:"namecode"` 
    DateEntered time.Time `xml:"enterdate"` //this is the field in question 
    Gross float64 `xml:"gross"` 
    Container TransactionDetailContainer `xml:"subfile"` 
} 

Il formato della data restituita è "aaaammgg".

+0

Questo può aiutare, anche se si occupa solo di marshalling. https://groups.google.com/forum/#!topic/golang-nuts/IM3ZIcYXbz4 – Intermernet

+0

Inoltre, dai un'occhiata a https://code.google.com/p/go/issues/detail?id=2771 – Intermernet

risposta

40

Ho avuto lo stesso problema.

time.Time non soddisfa l'interfaccia xml.Unmarshaler. E non puoi specificare una data fomat.

Se non si desidera gestire l'analisi dopo e si preferisce lasciare che il xml.encoding lo fanno, una soluzione è quella di creare una struttura con una time.Time campo anonimo e implementare il proprio UnmarshalXML con il formato della data personalizzato.

type Transaction struct { 
    //... 
    DateEntered  customTime  `xml:"enterdate"` // use your own type that satisfies UnmarshalXML 
    //... 
} 

type customTime struct { 
    time.Time 
} 

func (c *customTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 
    const shortForm = "20060102" // yyyymmdd date format 
    var v string 
    d.DecodeElement(&v, &start) 
    parse, err := time.Parse(shortForm, v) 
    if err != nil { 
     return err 
    } 
    *c = customTime{parse} 
    return nil 
} 

Se il vostro elemento XML utilizza un attribut come una data, è necessario implementare UnmarshalXMLAttr allo stesso modo.

Vedi http://play.golang.org/p/EFXZNsjE4a

+0

Questo mi ha fatto prendere la strada giusta. Era ancora più facile da gestire quando eseguivo 'customTime time.Time' - non c'era bisogno di gestire il' time.Time' sottostante come elemento struct. – Colselaw

+1

Attenzione che DecodeElement restituisce un errore, che dovrebbe essere controllato e restituito se non è nullo. – AndreiM

1

Da quello che ho letto la codifica/xml ha alcuni problemi noti che sono stati messi fuori fino a una data successiva ...

per aggirare questo problema, invece di utilizzare il tipo time.Time uso string e gestire il analizzando in seguito.

ho avuto un po 'di difficoltà a raggiungere Time.parse di lavorare con le date nel seguente formato: "Ven, 9 agosto 2013 19:39:39 GMT"

Stranamente ho scoperto che "net/http "ha una funzione ParseTime che accetta una stringa che ha funzionato perfettamente ... http://golang.org/pkg/net/http/#ParseTime

+0

La cosa più strana, non appena ho impostato il tipo di un campo data per stringere tutto ha iniziato l'analisi .... –