1 mongodb中的utc时间问题:
今天遇到了这么一个需求,把北京时间今日零时到当前的所有记录都查找出来。
第一个反应就是这涉及到范围问题,只需要先把年、月、日按照当前的$match过滤一遍,然后再把小时按照从0到当前的滤一遍,就可以得到结果了。但是我的想法是错的,因为时间标准不统一,业务中的代码采用的是北京时间,而数据库中存储的是utc时间,中间差了8个小时。要知道,相差8个小时,不仅仅是相差了1天,还有可能相差了1年、1月,所以知道这点后我就写出了如下的代码:
【nodejs环境】
// 将北京时间今日0点构造成utc时间 var d0 = new Date(); d0.setMinutes( 0 ); d0.setSeconds( 0 ); d0.setHours( d0.getHours() - 8 ); // 将北京当前时间构造成utc时间 var dn = new Date(); dn.setHours( dn.getHours() - 8 ); ……………… // 只写管道中的代码 { $project : { year : {$year : "$date"}, month : {$month : "$date"}, day : {$dayOfMonth : "$date"}, hour : {$hour : "$date"}, err : 1, date : 1 } }, { $match : { year : { $gte : d0.getFullYear(), $lte : dn.getFullYear() }, month : { $gte : d0.getMonth() + 1, $lte : dn.getMonth() + 1 }, day : { $gte : d0.getDate(), $lte : dn.getDate() }, err : "bad request 400" } }, { $group : { _id : { "year" : "$year", "month" : "$month", "day" : "$day", "hour" : "$hour" }, count : { $sum : 1 } } }
可以看出来,当时我非常愚蠢的把年月日分别做比较,这样一来无端增添了不必要的代码。
晚上回家继续琢磨这个问题,思考有没有更好的解决方法,翻看《mongodb权威指南(第二版)》的时候,看到了类似这样的用法:$hour : "$date";
这提醒了我在调价中可以直接构造一个变量,然后mongodb会自动把这个变量转化成utc标准?实验了一下果然可以,代码少了不少。
// 将北京时间今日0点构造成utc时间 var d0 = new Date(); d0.setMinutes( 0 ); d0.setSeconds( 0 ); d0.setHours( 0 ); // 将北京当前时间构造成utc时间 var dn = new Date(); ……………… // 只写管道部分代码 { $project : { hour : {$hour : "$date"}, err : 1, date : 1 } }, { $match : { date : { $gte : d0, $lte : dn }, err : "bad request 400" } }, { $group : { _id : { "hour" : "$hour" }, count : { $sum : 1 } } }
可以看到代码明显精简了。
小结:可以在mongodb中进行比较,mongodb会自动把北京时间转换为utc时间,这点可以利用起来。
浙公网安备 33010602011771号