If I store ISODate in mongodb,the ISODate is always GMT+0
type StoreTime struct {
storeTime time.Time `bson:"testTime" json:"testTime,omitempty"`
}
...
t := StoreTime {
storeTime : time.Now(),
}
....
c.Insert(t)
The result is :
{
"_id" : ObjectId("578b43e5feaa0deb6a94b1d0"),
"storeTime" : ISODate("2016-07-17T08:38:25.316+0000")
}
How can I change the time zone?
time.Now
should return local time. Is your system time setup properly? What do you get on running the date
command (on linux based system)?
You can try using In
method on you time
object with a time.Location
value:
l, _ := time.LoadLocation("Local") // or the name of your time zone
t : time.Now()
t := StoreTime {
storeTime : t.In(l),
}
You came across an intricacy of mgo.v2/bson, which converts Since the BSON specification states that all times shall be stored as
UTC milliseconds since the Unix epoch
mgo.v2/bson
converts all time.Time values to UTC. So even when you explicitly set the location info of a time returned by time.Now()
or companions, this local time is converted to UTC.
So in order to display time correctly for any given time zone, you should do the following:
time.Time.In(*time.Location)
if the time zone differs from your (the servers) local time.time.Time.UTC()
time.Time.In(*time.Location)
again.To be a more clear on that, please have a look at the example below:
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))
}