2016-08-27 3 views
3

фон

Я учусь Go, и я пытаюсь сделать некоторые JSON демаршалинга из Задан.неправильно отформатирована распаковать DateTime в Golang

У меня есть JSON, созданный программой, которую я написал в C, я выводил то, что я считал действительным /RFC3339 смещение часового пояса. Я использую strftime со следующей строкой формата:

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

(Обратите внимание, что %f не поддерживается strftime изначально, у меня есть оболочка, которая заменяет его с наносекундами).

Это будет производить следующий результат:

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

демаршалинга это в Go, однако, не будет работать: 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) 
} 

Выход:

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

(Рабочий пример: https://play.golang.org/p/5xcM0aHsSw)

Это потому, что RFC3339 expects the timezone offset to be in the format 02:00 с :, но strftime выводит его как 0200.

Поэтому мне нужно исправить это в моей программе на C, чтобы вывести правильный формат.

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

Вопрос

Однако, теперь у меня есть куча JSON файлов с этим неправильным форматом:

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

вместо правильного (с : в часовом поясе смещение):

2016-08-08T21:35:14.052975+02:00 

, но я все еще хочу иметь возможность правильно его размонтировать в моей программе Go. Предпочтительно два разных файла JSON с такой разницей должны одинаково разбираться.

Что касается маршалинга назад к JSON, следует использовать правильный формат.

Это, как я определил это в моем struct:

Time   time.Time `json:"time"` 

Так что вопрос в том, что в «Go» способ сделать это?

Также в моем примере кода я использую RFC3339Nano. Как я могу указать это в метаданных для структуры? Как я уже сейчас, только json:"time" будет игнорировать nano секунд?

+0

Возможный дубликат [json unmarshal time, который не находится в формате RFC 3339] (http://stackoverflow.com/questions/25087960/json-unmarshal-time-that-isnt-in-rfc-3339-format) –

ответ

10

Вы можете определить свой собственный тип time поля, которое поддерживает оба формата:

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

В приведенном выше примере мы берем предопределенные формат time.RFC3339Nano, который определяется как t его:

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

и удалить :

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

Этот формат времени, используемый time.Parse описано здесь: https://golang.org/pkg/time/#pkg-constants

см также документацию для time.Parse https://golang.org/pkg/time/#Parse

P.S. Тот факт, что год 2006 используется в строках формата времени, вероятно, потому, что в этом году была выпущена первая версия Golang.

-1

Вы можете попробовать 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) 
}