How can I get the UTC time when I query mongodb in golang

huangapple go评论98阅读模式
英文:

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 &lt; 0 || y &gt;= 10000 {
return nil, errors.New(&quot;JsonTime: year outside of range [0,9999]&quot;)
}
if y := tt.Year(); y == 1 {
return []byte{}, nil
}
return []byte(tt.Format(`&quot;` + time.RFC3339Nano + `&quot;`)), 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(&amp;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:&quot;_id,omitempty&quot; json:&quot;-&quot;`
SampleDate JsonTime      `bson:&quot;sampleDate&quot; json:&quot;sampleDate&quot;`
}
func TestMe() {
var item SampleItem
var items []SampleItem
sess := getSession()
defer sess.Close()
item.SampleDate = JsonTime(time.Now().UTC())
fmt.Printf(&quot;%s\n&quot;, item.SampleDate)
collection := sess.DB(&quot;myCollection&quot;).C(&quot;sampleItems&quot;)
collection.Insert(item)
err := collection.Find(bson.M{}).All(&amp;items)
if err == nil {
fmt.Printf(&quot;%s\n&quot;, items[0].SampleDate)
if data, err := json.Marshal(items); err != nil {
fmt.Printf(&quot;%v\n&quot;, err)
} else {
fmt.Printf(&quot;%s\n&quot;, data)
}
}
}

huangapple
  • 本文由 发表于 2014年10月12日 12:44:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/26321961.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定