2016-08-23 1 views
0

(Bearbeiten/update): Danke an @djd für den Hinweis, dass wir alle JSON/struct Dekodierung überspringen können; Das Schlüsselproblem ist mit time.Parse.Golang leer Ort auf Mac OSX beim Parsen

Das gleiche Problem kommt hier, wo die Location „leer“ ist eher als UTC (I UTC erwartet habe auf der Dokumentation basieren würde: https://golang.org/pkg/time/#Parse

„In Ermangelung einer Anzeige Zeitzone, Parse liefert eine . Zeit in UTC“

Hier ist der Beispielcode: https://play.golang.org/p/pb3eMbjSmv

package main 

import (
    "fmt" 
    "time" 
) 

func main() { 
    // Ignoring the err just for this example's sake! 
    parsed, _ := time.Parse(time.RFC3339, "2017-08-15T22:30:00+00:00") 
    fmt.Printf("String(): %v\n", parsed.String()) 
    fmt.Printf("Location(): %v\n", parsed.Location()) 
} 

die

ausgibt

So, während der Offset der time.TimeLocation scheint korrekt zu sein, ist seine Zeitzone Name nur eine leere Zeichenfolge. Auf anderen Computern (und The Go Playground) wird der erwartete "UTC" -Standort angezeigt.

[Original-Beitrag]:

Wenn ein Feld Zeitstempel Dekodieren von JSON in eine struct auf meinem lokalen OS X-Maschine, die Location des time.Time Feld ist „leer“ statt UTC. Dies ist problematisch, wenn ich Komponententests lokal ausführe (im Gegensatz zu einem CI-Server, auf dem Location korrekt auf UTC eingestellt ist).

Wenn ich das auf meinem Rechner laufen, sehe ich

go run main.go TimeField.String(): 2017-08-15 22:30:00 +0000 +0000 TimeField.Location():

So, während der Versatz der time.Time ‚s Location scheint korrekt zu sein, dessen Name der Zeitzone nur eine leere Zeichenfolge ist. Dies geschieht mit Hilfe Go 1.5:

go version go version go1.5 darwin/amd64

+0

Um zu vereinfachen, ist der 'json' Teil tatsächlich irrelevant: die UnmarshalJSON Methode ist nur ein Wrapper um time.Parse mit dem RFC3339 Format String: ' time.Parse (time.RFC3339, "2017-08-15T22: 30 : 00 + 00: 00 ")' – djd

+0

Danke @djd, aktualisierte Beschreibung der Frage zu vereinfachen und einfach 'time.Parse' zu ​​verwenden. – nrjones8

+0

[Dieser Code] (https://golang.org/src/time/format.go#L1015) in 'time/format.go' scheint als könnte es ein wahrscheinlicher Täter sein, aber es erklärt nicht unbedingt warum Das Verhalten ist auf meinem lokalen Mac OS X-Computer anders als auf dem CI-Server, den wir verwenden (Linux) oder was auch immer Go Playground verwendet. – nrjones8

Antwort

0

I gleiches Verhalten mit meinem aktuellen Setup auf Mac finden und ich vermute, es wird elbe Verhalten auf Linux (nicht sicher durch)

$ go version 
go version devel +31ad583 Wed Aug 10 19:44:08 2016 +0000 darwin/amd64 

Um es sein mehr deterministisch, schlage ich vor, eine benutzerdefinierte json Unmarshal wie folgt zu verwenden:

package main 

import (
    "encoding/json" 
    "fmt" 
    "strings" 
    "time" 
) 

type Time struct { 
    *time.Time 
} 

func (t *Time) UnmarshalJSON(b []byte) error { 
    const format = "\"2006-01-02T15:04:05+00:00\"" 
    t_, err := time.Parse(format, string(b)) 
    if err != nil { 
     return err 
    } 
    *t = Time{&t_} 
    return nil 
} 

type Example struct { 
    TimeField *Time `json:"time_field"` 
} 

func main() { 
    inString := "{\"time_field\": \"2017-08-15T22:30:00+00:00\"}" 
    var ex Example 
    decoder := json.NewDecoder(strings.NewReader(inString)) 
    decoder.Decode(&ex) 
    fmt.Printf("TimeField.String(): %v\n", ex.TimeField.String()) 
    fmt.Printf("TimeField.Location(): %v\n", ex.TimeField.Location()) 
} 
0

Ja, Sie haben Recht. On The Go Spielplatz ist die Local-UTC innerhalb dieser Sandbox gesetzt:
dieses Arbeitsbeispielcode Versuchen Sie, auf The Go Playground:

package main 

import (
    "fmt" 
    "runtime" 
    "time" 
) 

func main() { 
    fmt.Println(runtime.Version(), runtime.GOARCH, runtime.GOOS) //go1.7 amd64p32 nacl 

    parsed, err := time.Parse(time.RFC3339, "2017-08-15T22:30:00+00:00") 
    if err != nil { 
     panic(err) 
    } 
    fmt.Printf("String(): %v\n", parsed.String()) 
    fmt.Printf("Location(): %v\n", parsed.Location()) 
} 

Ausgang auf der Go Spielplatz:

go1.7 amd64p32 nacl 
String(): 2017-08-15 22:30:00 +0000 UTC 
Location(): UTC 

Und versuchen Sie es auf Ihr lokales System, Ausgabe Location() ist leer.


Sie verwenden können utc := parsed.UTC() mit der Lage auf UTC eingestellt, wie dieser Arbeitsbeispielcode The Go Playground:

package main 

import (
    "fmt" 
    "runtime" 
    "time" 
) 

func main() { 
    fmt.Println(runtime.Version(), runtime.GOARCH, runtime.GOOS) //go1.7 amd64p32 nacl 

    parsed, err := time.Parse(time.RFC3339, "2017-08-15T22:30:00+00:00") 
    if err != nil { 
     panic(err) 
    } 
    fmt.Printf("String(): %v\n", parsed.String()) 
    fmt.Printf("Location(): %v\n", parsed.Location()) 
    utc := parsed.UTC() 
    fmt.Printf("String(): %v\n", utc.String()) 
    fmt.Printf("Location(): %v\n", utc.Location()) 
} 

auch Sie könnten time.ParseInLocation(time.RFC3339, "2017-08-15T22:30:00+00:00", time.UTC) verwenden, wie dieser Arbeitsbeispielcode:

package main 

import (
    "fmt" 
    "runtime" 
    "time" 
) 

func main() { 
    fmt.Println(runtime.Version(), runtime.GOARCH, runtime.GOOS) //go1.7 amd64p32 nacl 

    parsed, err := time.ParseInLocation(time.RFC3339, "2017-08-15T22:30:00+00:00", time.UTC) 
    if err != nil { 
     panic(err) 
    } 
    fmt.Printf("String(): %v\n", parsed.String()) 
    fmt.Printf("Location(): %v\n", parsed.Location()) 
} 

Also wird Location()UTC sein.