Golang / mgo:如何在mongodb中通过GMT + 8时区存储ISODate?

时间:2016-07-17 09:11:58

标签: mongodb go

如果我将ISODate存储在mongodb中,则ISODate始终为GMT + 0

type StoreTime struct {
    storeTime time.Time `bson:"testTime" json:"testTime,omitempty"`
}
...
t := StoreTime {
    storeTime : time.Now(),
}
....
c.Insert(t)

结果是:

{ 
    "_id" : ObjectId("578b43e5feaa0deb6a94b1d0"),  
    "storeTime" : ISODate("2016-07-17T08:38:25.316+0000")
}

如何更改时区?

2 个答案:

答案 0 :(得分:3)

你遇到了一个复杂的mgo.v2 / bson,它转换因为BSON specification表示所有时间都应存储为

  

自Unix纪元以来的UTC毫秒

mgo.v2/bson将所有time.Time值转换为UTC。因此,即使您明确设置time.Now()或同伴返回的时间的位置信息,此本地时间也会转换为UTC。

因此,为了正确显示任何给定时区的时间,您应该执行以下操作:

  1. 保存time.Time值时,如果时区与您(服务器)当地时间不同,则应使用time.Time.In(*time.Location)返回的时间。
  2. 以UTC格式显示返回值时,请务必使用time.Time.UTC()
  3. 在给定的本地时间显示返回值时,请确保再次使用time.Time.In(*time.Location)
  4. 为了更清楚,请看下面的例子:

    package main
    
    import (
        "fmt"
        "time"
    
        "gopkg.in/mgo.v2"
        "gopkg.in/mgo.v2/bson"
    )
    
    const (
        myLoc = "Europe/Berlin"
        ny    = "America/New_York"
    )
    
    // We define those vars here, as you might want to make them
    // package-global
    var (
        berlin *time.Location
        nyc    *time.Location
    )
    
    // StoreTime is just a dummy struct
    type StoreTime struct {
        // Unexported fields are not (un-)marshalled by encoding/json
        // and mgo.v2/bson, so the field name has to be uppercase
        StoreTime time.Time `bson:"testTime"`
    }
    
    func main() {
    
        var (
            sess *mgo.Session
            err  error
        )
    
        // Connect to MongoDB
        if sess, err = mgo.Dial("localhost:27017"); err != nil {
            panic("Could not connect to MongoDB: " + err.Error())
        }
        // Make sure the session is closed when main exits for whatever reason
        defer sess.Close()
    
        // Clear the collection for demo purposes
        if err = sess.DB("test").C("timezones").Remove(bson.M{}); err != nil && err != mgo.ErrNotFound {
            panic("Could not clean test collection: " + err.Error())
        }
    
        // Load the desired TZ by location
        if berlin, err = time.LoadLocation(myLoc); err != nil {
            panic("Error loading '" + myLoc + "' as timezone location: " + err.Error())
        }
    
        // Create a new StoreTime with the local time of the desired timezone.
        // Note that mgo.v2/bson still converts it to Zulu time, but with the
        // appropriate offset.
        st := &StoreTime{StoreTime: time.Now().In(berlin)}
    
        // Save the document for further reference
        if err = sess.DB("test").C("timezones").Insert(st); err != nil {
            panic("Error inserting sample document into MongoDB: " + err.Error())
        }
    
        // Load the saved document,...
        res := &StoreTime{}
        if err = sess.DB("test").C("timezones").Find(nil).One(&res); err != nil {
            panic("Unable to load just recently stored document: " + err.Error())
        }
    
        // ... and another TZ for displaying,...
        if nyc, err = time.LoadLocation(ny); err != nil {
            panic("Error loading '" + ny + "' as timezone location: " + err.Error())
        }
    
        // ...and display the time from the document in UTC and the local time
        // of both Berlin and NYC.
        fmt.Println(res.StoreTime.UTC())
        // The next two are identical for _me_, as I happen to live in the according TZ.
        // Unless you do, too, you should have different values
        fmt.Println(res.StoreTime.In(Berlin))
        fmt.Println(res.StoreTime)
        fmt.Println(res.StoreTime.In(nyc))
    }
    

答案 1 :(得分:0)

time.Now应返回当地时间。您的系统时间设置正确吗?运行date命令(在基于Linux的系统上)会得到什么?

您可以尝试在In对象上使用time方法time.Location值:

l, _ := time.LoadLocation("Local") // or the name of your time zone
t : time.Now()

t := StoreTime {
    storeTime : t.In(l),
}