网上有关于很多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) }) })
扫码联系船长