MongoDB的时间类型和ObjectID的时间依据

网上有关于很多MongoDB时间存储格式Date的讨论。其实核心的点就在于Mongodb中以Date格式存储的数据默认为是UTC时间。简单来讲,例如当前我们是早上8点,我们在时区设置为正8区的电脑上使用使用python的datetime.now()获取的时间就是早上8点。但是我们把这个时间不做任何处理,直接存放到MongoDB中的Date类型字段中,就变成了UTC时间(0时区)的早上8点。那么这种情况会带来什么问题呢?

如图所示,我们把北京时间8点的数据存入Mongodb中Date类型的字段,会被存储如下类型:

如果我们使用Node.js写一段代码,获取上节中插入的数据,显示出来的时间如图:

时间被自动加上了8个小时。在NodeJS中的MongoDB连接器会自动把MongoDB返回的UTC时间转换为本地时间(也就是北京时间)。所以如果在MongoDB中存储为UTC时间(0时区)早上8点,那么程序显示出来的时间就变为北京时间16点。

因此我们在存储之前就要考虑使用UTC的时间格式把数据存入MongoDB中,例如使用python的datetime.utcnow()

ObjectID中的时间格式
MongoDB中会自动创建ObjectID,ObjectId的前4个字节表示时间。默认情况下,前4个字节表示的时间为文件创建时服务器的时间。需要注意的是,即使是服务器时间,在MongoDB中也会转化为UTC时间存储。例如,我们在北京时间8点插入一条数据,ObjectId的前4个字节会保存UTC的时间。例如,如果在python中需要获取北京时间早上8点插入的数据,那么需要把构成ObjectId时间转换为UTC时间。例如:

today = datetime(2020, 10, 6, 8, 0, 0)
today = today - timedelta(seconds=28800)
todayId = ObjectId.from_datetime(generation_time=today)
query = {"_id":{"$gte":todayId}}
sort = [("_id", 1)]
data = db['collection'].find(query).sort(sort).limit(10)
for item in data:
    print(item)

另外需要特别注意的是,JS的date.getTime()获取的时间是转换为UTC后的时间。因此,使用NodeJS获取MongoDB数据时,不需要手动调整时间。例如:

var objectIdFromDate = function (date) {
    return Math.floor((date.getTime())/ 1000).toString(16) + "0000000000000000";
};
const fromDate = new Date('2020-10-06 8:00:00');
const fromDateStr = objectIdFromDate(fromDate)
const query = {
    _id:{'$gte': ObjectId(fromDateStr)},
}
db.collection('alpha').find(query).limit(10).sort({"_id":1}).toArray().then(result => {
    result.forEach(ele => {
        console.log(ele)
    })
})
Captain QR Code

扫码联系船长

发表回复

您的电子邮箱地址不会被公开。