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



如果我将 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")
}

如何更改时区?

你遇到了一个错综复杂的mgo.v2/bson,它转换 由于BSON规范规定所有时间都应存储为

自 Unix 纪元以来的 UTC 毫秒

mgo.v2/bson一直转换。时间值为 UTC。因此,即使您显式设置了time.Now()或同伴返回的时间的位置信息,此本地时间也会转换为 UTC。

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

  1. 节省时间时。时间值,如果时区与您(服务器)的本地时间不同,则应使用time.Time.In(*time.Location)返回的时间。
  2. 以 UTC 格式显示返回值时,请确保使用 time.Time.UTC()
  3. 在给定的本地时间显示返回值时,请确保再次使用 time.Time.In(*time.Location)

为了更清楚地说明这一点,请看下面的例子:

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))
}

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

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

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

最新更新