LoginSignup
9
4

More than 3 years have passed since last update.

MongoDBに挿入された時刻の仕様調査: MongoDB内の時刻はUTC(タイムゾーンなし)・msecまで

Last updated at Posted at 2019-06-25

はじめに

GoでMongo周りのコーディングをしてた際に、「TimestampをMongoDBに詰めると値が変わってしまう」って話が出てたので、仕様を確認しました。

Mongoの時刻に関する挙動: time.Timeと情報が異なる

例えば以下のようなMongoDBにtime.Timeで時刻を取って、Mongoにinsert, findしてみます。

main.go
package main

import (
        "fmt"
        "time"

        "github.com/globalsign/mgo"
        "github.com/globalsign/mgo/bson"
        "github.com/google/uuid"
)

type MyDoc struct {
        ID   uuid.UUID
        Time time.Time
}

func main() {
        dbname := "sampleDocument"
        connection, _ := mgo.Dial("mongodb://localhost/" + dbname)
        db := connection.DB(dbname)

        //元ネタとなる時刻取得
        doc := MyDoc{uuid.New(), time.Now()}
        fmt.Printf("data in time.Time:[%v]\n", doc)
        //insert
        collection := db.C("doc")
        collection.Insert(doc)

        //中身の確認
        var getFromMongo MyDoc
        collection.Find(bson.M{"id": doc.ID}).One(&getFromMongo)
        fmt.Printf("data in Mongo:[%v]\n", getFromMongo)
}

上記の実行結果はこんな感じ。

項目 time.Time.Now() Mongo
精度 nanosecond millisecond
タイムゾーン JST UTC
$ go run main.go
data in time.Time:[{b7350e5d-05d0-429a-9d51-1eb365e71d76 2019-06-25 23:11:36.706508427 +0900 JST m=+0.001236469}]
data in Mongo:[{b7350e5d-05d0-429a-9d51-1eb365e71d76 2019-06-25 14:11:36.706 +0000 UTC}]

実際のMongoDBに入っている情報を確認しても情報が消えています。つまりmongo自体の仕様か、可能性は低そうですがGolangのinsert部分に関するmongo用ドライバの問題である可能性があります。
ISODateという形式で入っていることから、mongoの仕様として変換してるんだろうなということが予想されます。

> db.doc.find()
{ "_id" : ObjectId("5d122aa6bf374055deac672e"), "id" : BinData(0,"ugCCZy0ERyWRZRk+V2fxIw=="), "time" : ISODate("2019-06-25T14:07:34.331Z") }

Mongoの時刻仕様

Mongoでは、BSONと呼ばれるデータフォーマットでデータを保存しています。その仕様を確認すると以下のようになっています。
下記で分かるように1. タイムゾーンはUTC, 2. データの精度はmillisecondとなります。

UTC datetime - The int64 is UTC milliseconds since the Unix epoch.

MongoDBのDate仕様も確認。Date()の記載より

new Date("YYYY-mm-ddTHH:MM:ss") specifies the datetime in the client’s local timezone and returns the ISODate with the specified datetime in UTC.

実行時にタイムゾーン指定がない場合は、マシンのタイムゾーンで計算⇒UTC時刻を返却としていますね。

同様にBehaviorより、millisecondなのが分かります。

Internally, Date objects are stored as a signed 64-bit integer representing the number of milliseconds since the Unix epoch (Jan 1, 1970).

というわけで、以下が仕様であることが分かりました。

項目 time.Time.Now() Mongo
精度 nanosecond millisecond
タイムゾーン JST UTC

参考

BSON Specification Version 1.1
MongoDB Date()
Stack overflow: Nanoseconds lost coming from MongoDB ISODate Object
mongoのISODateのtimezone問題に対処する

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4