如何修改JSON对象数组中Date类型字段仅保留年月日日期部分
需求场景
- 技术栈:MongoDB + Express
- 服务端通过
find方法查询得到名为upProbations的JSON对象数组,原始返回示例:
[ { Name: 'Max', DateOne: 2019-01-01T00:00:00.000Z, DateTwo: 2019-04-01T00:00:00.000Z, Info: 'Cheerful' } ]
- 目标:将数组中
DateOne、DateTwo两个Date类型字段的时分秒毫秒部分移除,仅保留YYYY-MM-DD格式的年月日,期望输出格式:
[ { Name: 'Peter', DateOne: '2019-01-01', DateTwo: '2019-04-01', Info: 'Cheerful' } ]
- 之前尝试的map遍历写法未生效,代码如下:
upProbations = upProbations.map(function(a) { a.DateOne = a.DateOne.toISOString().replace('T', ' ').substr(0, 10); return a; }) console.log(upProbations);
失效原因
- 如果使用Mongoose作为MongoDB驱动,默认
find返回的是Mongoose Document实例,不是普通JavaScript对象,直接修改实例属性会被内部的getter/setter逻辑拦截,赋值不会实际生效,打印时仍会展示原始Date类型值。 - 直接调用
toISOString()截取前10位的写法取的是UTC标准时区的日期,如果服务端部署在非0时区,会出现日期偏移1天的问题,比如东八区凌晨0点的时间,转ISO字符串会显示为前一天的16点,截取后得到的日期会比实际日期早1天。
实现方案
方案1:查询阶段直接格式化(性能最优)
直接在MongoDB查询时通过$dateToString操作符完成日期格式化,配合lean()返回普通JS对象,省去后续遍历处理的开销:
// MongoDB 4.4+版本支持在find投影中使用聚合表达式 const upProbations = await ProbationModel.find( { /* 填入你的查询条件,比如Name: 'Max' */ }, { Name: 1, Info: 1, DateOne: { $dateToString: { format: '%Y-%m-%d', date: '$DateOne', timezone: 'Asia/Shanghai' } }, DateTwo: { $dateToString: { format: '%Y-%m-%d', date: '$DateTwo', timezone: 'Asia/Shanghai' } } } ).lean();
注意:timezone参数替换为你业务实际使用的时区,避免日期偏移问题。
方案2:查询结果遍历处理(兼容性最好)
查询时加lean()拿到普通JS对象后,再遍历处理日期字段,用本地时间方法拼接日期字符串,避免时区问题:
// 第一步:加lean()查询得到普通JS对象数组 let upProbations = await ProbationModel.find({ /* 查询条件 */ }).lean(); // 第二步:遍历处理两个日期字段 upProbations = upProbations.map(item => { // 处理DateOne const d1 = new Date(item.DateOne); item.DateOne = `${d1.getFullYear()}-${String(d1.getMonth() + 1).padStart(2, '0')}-${String(d1.getDate()).padStart(2, '0')}`; // 处理DateTwo const d2 = new Date(item.DateTwo); item.DateTwo = `${d2.getFullYear()}-${String(d2.getMonth() + 1).padStart(2, '0')}-${String(d2.getDate()).padStart(2, '0')}`; return item; }); console.log(upProbations);
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

