Как я могу получить время UTC, когда я запрашиваю mongodb в golang

Я относительно новичок в Golang и MongoDB и столкнулся с проблемой даты, когда кажется, что я могу вставить дату UTC в MongoDB, но когда я запрашиваю через Golang, она автоматически преобразуется в местное время. Я хочу получить его обратно из MongoDB в формате UTC без преобразования. Вот краткий пример:

type SampleItem struct {
    ObjId      bson.ObjectId `bson:"_id,omitempty" json:"-"`
    SampleDate time.Time     `bson:"sampleDate" json:"sampleDate"`
}

func TestMe() {

    var item SampleItem
    var items []SampleItem

    sess := getSession()
    defer sess.Close()

    item.SampleDate = time.Now().UTC()
    fmt.Printf("%s\n", item.SampleDate)

    collection := sess.DB("myCollection").C("sampleItems")
    collection.Insert(item)

    err := collection.Find(bson.M{}).All(&items)
    if err == nil {
        fmt.Printf("%s\n", items[0].SampleDate)
    }
}

Мой вывод:

2014-10-12 04:10:50.3992076 +0000 UTC

2014-10-11 23:10:50.399 -0500 CDT

Похоже, что драйвер mgo может автоматически преобразовывать его, потому что, когда я запрашиваю mongodb из окна консоли, моя дата указана в формате UTC. Я где-то пропустил опцию mgo, которая отключает это?


person jzapata    schedule 12.10.2014    source источник


Ответы (2)


Значения Go time.Time сохраняют момент времени и местоположение. Декодер mgo BSON устанавливает местоположение time.Local.

Вы можете установить time.Local для местоположения UTC:

time.Local = time.UTC

Пакет, предназначенный для использования третьими сторонами, не должен изменять локальное расположение, но это допустимо в рамках приложения.

Метод Time.UTC() возвращает время в тот же момент времени, что и получатель, и местоположение установлено в UTC. Эта строка напечатает время в формате UTC:

    fmt.Printf("%s\n", items[0].SampleDate.UTC())

Поскольку MongoDB хранит время с меньшей точностью, чем time.Time, значение, возвращаемое MongoDB, может не совпадать со значением, которое вы сохранили.

person Cerise Limón    schedule 12.10.2014
comment
OK. Часть моей проблемы заключается в том, что я сериализуюсь в json, что-то вроде этого: data, err := json.Marshal(items[0]); Данные json - неправильное время. Как я могу получить вывод json для сериализации в UTC? - person jzapata; 13.10.2014
comment
Мне нравится простота, Чарли, но я бы хотел, чтобы мне не нужно было помнить, чтобы установить UTC перед сериализацией в json. Я изучил создание пользовательского типа из time.Time, который позволил бы мне установить собственный сериализатор json, использующий UTC. Я опубликую это как возможный ответ, но меня интересуют любые комментарии от тех, у кого больше опыта, о том, хороший ли это вариант или нет. - person jzapata; 15.10.2014
comment
Это именно то, что я искал. Кажется, это дает мне то, что мне нужно. Спасибо. - person jzapata; 15.10.2014

Я знаю, что задавал этот вопрос, но после долгих поисков я обнаружил, что это один из возможных вариантов. Используя пользовательский тип из time.Time, вы можете переопределить интерфейсы сериализатора json и принудительно использовать UTC. Тем не менее, рекомендуется ли делать такие вещи...

Я должен отдать должное времени UNIX. штампы на Голанге, а также источник go.

type JsonTime time.Time

func (t JsonTime) MarshalJSON() ([]byte, error) {
    tt := time.Time(t).UTC()
    if y := tt.Year(); y < 0 || y >= 10000 {
        return nil, errors.New("JsonTime: year outside of range [0,9999]")
    }
    if y := tt.Year(); y == 1 {
        return []byte{}, nil
    }
    return []byte(tt.Format(`"` + time.RFC3339Nano + `"`)), nil
}

func (t JsonTime) GetBSON() (interface{}, error) {
    if time.Time(t).IsZero() {
        return nil, nil
    }
    return time.Time(t), nil
}

func (t *JsonTime) SetBSON(raw bson.Raw) error {
    var tm time.Time

    if err := raw.Unmarshal(&tm); err != nil {
        return err
    }

    *t = JsonTime(tm)
    return nil
}

func (t JsonTime) String() string {
    return time.Time(t).UTC().String()
}

type SampleItem struct {
    ObjId      bson.ObjectId `bson:"_id,omitempty" json:"-"`
    SampleDate JsonTime      `bson:"sampleDate" json:"sampleDate"`
}

func TestMe() {

    var item SampleItem
    var items []SampleItem

    sess := getSession()
    defer sess.Close()

    item.SampleDate = JsonTime(time.Now().UTC())
    fmt.Printf("%s\n", item.SampleDate)

    collection := sess.DB("myCollection").C("sampleItems")
    collection.Insert(item)

    err := collection.Find(bson.M{}).All(&items)
    if err == nil {

        fmt.Printf("%s\n", items[0].SampleDate)
        if data, err := json.Marshal(items); err != nil {
            fmt.Printf("%v\n", err)
        } else {
            fmt.Printf("%s\n", data)
        }
    }
}
person jzapata    schedule 15.10.2014