使用MongoDB聚合将字符串转为ISO日期,非法格式设为null
MongoDB 自定义日期转ISO日期(兼容非法格式)
原始数据
[ { _id: 1, value: "8 Aug 2022, 1:13 PM" }, { _id: 2, value: "15 Aug 2022, 1:13 PM" }, { _id: 3, value: "Hello" }, { _id: 4, value: "32 Dec 2023, 25:61 AM" } ]
需求说明
将文档中value字段的自定义日期格式(如"8 Aug 2022, 1:13 PM")转换为标准ISO日期;若value格式非法(无法解析为有效日期),则将转换后的日期字段设为null。
改进后的聚合管道代码
aggregate([ { "$set": { "months": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], "parts": {"$split": ["$value", " "]} } }, { "$set": { "isValidFormat": {"$eq": [{"$size": "$parts"}, 5]}, "rawDay": {"$arrayElemAt": ["$parts", 0]}, "rawMonth": {"$arrayElemAt": ["$parts", 1]}, "rawYear": {"$replaceOne": {"input": {"$arrayElemAt": ["$parts", 2]}, "find": ",", "replacement": ""}}, "rawTime": {"$arrayElemAt": ["$parts", 3]}, "period": {"$arrayElemAt": ["$parts", 4]} } }, { "$set": { "day": {"$toInt": "$rawDay"}, "monthIndex": {"$indexOfArray": ["$months", "$rawMonth"]}, "year": {"$toInt": "$rawYear"}, "timeParts": {"$split": ["$rawTime", ":"]}, "isValidPeriod": {"$in": ["$period", ["AM", "PM"]]} } }, { "$set": { "hour": {"$toInt": {"$first": "$timeParts"}}, "minute": {"$toInt": {"$arrayElemAt": ["$timeParts", 1]}}, "isValidDay": {"$and": [{"$gte": ["$day", 1]}, {"$lte": ["$day", 31]}]}, "isValidMonth": {"$ne": ["$monthIndex", -1]}, "isValidYear": {"$ne": ["$year", null]}, "isValidHour": {"$and": [{"$gte": ["$hour", 1]}, {"$lte": ["$hour", 12]}]}, "isValidMinute": {"$and": [{"$gte": ["$minute", 0]}, {"$lte": ["$minute", 59]}]} } }, { "$set": { "allValid": { "$and": [ "$isValidFormat", "$isValidPeriod", "$isValidDay", "$isValidMonth", "$isValidYear", "$isValidHour", "$isValidMinute" ] }, "adjustedHour": { "$cond": [ {"$eq": ["$period", "PM"]}, {"$add": ["$hour", 12]}, {"$cond": [{"$eq": ["$hour", 12]}, 0, "$hour"]} ] } } }, { "$set": { "date": { "$cond": [ "$allValid", { "$dateFromParts": { "year": "$year", "month": {"$add": ["$monthIndex", 1]}, "day": "$day", "hour": "$adjustedHour", "minute": "$minute" } }, null ] } } }, { "$unset": ["months", "parts", "isValidFormat", "rawDay", "rawMonth", "rawYear", "rawTime", "period", "monthIndex", "timeParts", "isValidPeriod", "isValidDay", "isValidMonth", "isValidYear", "isValidHour", "isValidMinute", "allValid", "adjustedHour", "day", "year", "hour", "minute"] } ])
关键修改说明
- 格式校验层:通过
$size判断分割后的parts长度是否符合预期,校验周期是否为AM/PM,同时验证日期、月份、年份、小时、分钟的数值有效性。 - 错误处理逻辑:用
$cond结合综合校验结果allValid,仅当所有条件满足时执行$dateFromParts转换,否则返回null。 - 12小时制转24小时制优化:补充了12 AM转换为0点的逻辑,避免原代码中12 AM仍保留12点的错误。
内容的提问来源于stack exchange,提问作者vadapav
相关产品推荐
相关产品推荐

