dpmrakfbx820320638
dpmrakfbx820320638
2014-10-12 04:44

在Golang中查询mongodb时如何获得UTC时间

已采纳

I am relatively new to Golang and MongoDB and ran into a date issue where it appears that I can insert a UTC date into MongoDB, but when I query through Golang it is getting automatically converted to the local time. I want to get it back from MongoDB in UTC with no conversion. Here is a quick example:

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
", item.SampleDate)

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

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

My output:

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

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

It appears that the mgo driver may be automatically converting it because when I query mongodb from a console window my date is in UTC. Am I missing a mgo option somewhere that turns this off?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • douqie1852 douqie1852 7年前

    Go time.Time values store an instant in time and a location. The mgo BSON decoder sets the location to time.Local.

    You can set time.Local to the UTC location:

    time.Local = time.UTC
    

    A package designed to be used third parties should not modify the local location, but it's OK within the scope of an application.

    The Time.UTC() method returns a time at the same instant in time as the receiver and the location set to UTC. This line will print the time in UTC:

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

    Because MongoDB stores time with lower precision than a time.Time, the value returned from MongoDB may not equal the value you stored.

    点赞 评论 复制链接分享
  • dqbjvg2518 dqbjvg2518 7年前

    I know I asked this question, but after lots of digging around I found this to be one possible option. By using a custom type from time.Time you can override the json serializer interfaces and force the use of UTC. However, is doing this type of thing recommended...

    I have to give some credit to UNIX time stamps in Golang as well as the go source.

    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
    ", item.SampleDate)
    
        collection := sess.DB("myCollection").C("sampleItems")
        collection.Insert(item)
    
        err := collection.Find(bson.M{}).All(&items)
        if err == nil {
    
            fmt.Printf("%s
    ", items[0].SampleDate)
            if data, err := json.Marshal(items); err != nil {
                fmt.Printf("%v
    ", err)
            } else {
                fmt.Printf("%s
    ", data)
            }
        }
    }
    
    点赞 评论 复制链接分享

相关推荐