英文:
How can I get the UTC time when I query mongodb in golang
问题
我对Golang和MongoDB相对较新,遇到了一个日期问题:在向MongoDB插入UTC日期时,当我通过Golang查询时,它会自动转换为本地时间。我想以UTC格式从MongoDB中获取它,而不进行任何转换。这里是一个简单的示例:
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选项,可以关闭此功能?
英文:
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\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)
}
}
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?
答案1
得分: 10
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 返回的值可能与存储的值不相等。
英文:
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\n", 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.
答案2
得分: 0
我知道我问过这个问题,但是在大量搜索后,我发现这是一种可能的选择。通过使用自定义类型 time.Time,您可以重写 json 序列化接口并强制使用 UTC。然而,这种做法是否推荐呢...
我必须要给 Golang 中的 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)
}
}
}
英文:
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\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)
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论