如何将ISO格式日期时间设为0?Mongo日期对比问题
解决Mongo ISO日期与本地“今日”对比的时区问题
这个问题本质是本地时区和UTC时区的差异在搞鬼!你用setHours(0,0,0,0)设置的是本地时区的0点,但toISOString()会把日期转换成UTC时区的字符串,所以当你的本地时区是GMT-0800时,本地0点就等于UTC的8点,最终ISO字符串自然会显示T08:00:00.000Z。
下面根据你的实际需求,给出两种常用解决方案:
需求1:对比UTC时区的“今日”
如果你要找Mongo中属于UTC当天的记录(即ISO日期为YYYY-MM-DDT00:00:00.000Z到YYYY-MM-DDT23:59:59.999Z之间),直接基于UTC创建日期对象即可:
// 获取UTC时区的当天0点 const utcTodayStart = new Date(Date.UTC( new Date().getUTCFullYear(), new Date().getUTCMonth(), new Date().getUTCDate() )); // 获取UTC时区的次日0点(用于范围查询) const utcTodayEnd = new Date(utcTodayStart.getTime() + 24 * 60 * 60 * 1000); console.log(utcTodayStart.toISOString()); // 输出类似 "2018-01-20T00:00:00.000Z" console.log(utcTodayEnd.toISOString()); // 输出类似 "2018-01-21T00:00:00.000Z"
之后在Mongo中可以用范围查询:
db.collection.find({ yourDateField: { $gte: utcTodayStart, $lt: utcTodayEnd } })
需求2:对比本地时区的“今日”
如果你的业务逻辑是基于用户本地时区的“今天”(比如国内用户的北京时间当天),需要把本地时区的当天起止时间转换成UTC时区的范围,再去Mongo查询:
// 先获取本地时区的当天0点 const localTodayStart = new Date(); localTodayStart.setHours(0, 0, 0, 0); // 本地时区的次日0点 const localTodayEnd = new Date(localTodayStart.getTime() + 24 * 60 * 60 * 1000); // 转换成UTC格式的字符串(或Date对象)用于Mongo查询 const utcLocalStart = localTodayStart.toISOString(); // 示例输出 "2018-01-20T08:00:00.000Z" const utcLocalEnd = localTodayEnd.toISOString(); // 示例输出 "2018-01-21T08:00:00.000Z"
对应的Mongo查询:
db.collection.find({ yourDateField: { $gte: utcLocalStart, $lt: utcLocalEnd } })
关键提醒
Mongo中存储的日期默认都是UTC时区的,所以对比时一定要明确业务逻辑是基于UTC还是本地时区,避免因为时区偏移导致查询结果出错。
内容的提问来源于stack exchange,提问作者oneberenjena




