如何比较特定m_d_Y格式的JavaScript日期字符串
如何比较固定格式(m_d_Y)的日期字符串?
嘿,我来帮你捋捋这个日期比较的问题~你现在用的方法思路是对的,但存在一些容易踩坑的地方,咱们来聊聊最优的解决方案,以及怎么优化你的现有方法。
首先先说说你当前的compareDates函数:
你把日期拆分成月、日、年后,拼接成日+年+月的数字来比较,这种思路在部分场景下能得到正确结果,但有个致命隐患:当日期的年、月、日是个位数,或者跨年份比较时,会出现判断错误。比如1_9_2021(2021年1月9日)和12_10_2020(2020年12月10日),按你的方法会拼接成920211和10202012,数字比较会认为前者更小,但实际2021年的日期明显更大。
下面给你两种更稳妥的最优方案:
方案一:转换成Date对象直接比较
这是最直观、最不易出错的方法,Date对象本身就支持比较操作,还能自动处理闰年、不同月份天数等边界情况:
function compareDates(d1, d2) { // 拆分日期字符串,转成数字类型 const [month1, day1, year1] = d1.split('_').map(Number); const [month2, day2, year2] = d2.split('_').map(Number); // 注意:Date构造函数的月份是0-based(0代表1月,11代表12月),所以要减1 const dateCurrent = new Date(year1, month1 - 1, day1); const dateMax = new Date(year2, month2 - 1, day2); // Date对象可以直接用<=进行比较,返回布尔值 return dateCurrent <= dateMax; }
这个方法的优势:
- 可读性拉满,任何人看代码都能立刻明白是在处理日期比较
- 自动处理所有日期相关的边界问题,不用自己写逻辑判断
- 不需要手动处理补零等格式问题
方案二:标准化为YYYYMMDD格式的字符串比较
如果你担心Date对象的时区问题(比如业务完全不需要时区处理),可以把日期转换成YYYYMMDD格式的字符串,这种格式的字符串字典序和日期顺序完全一致,直接比较就行:
function compareDates(d1, d2) { // 补零工具函数,把单个数字转成两位字符串 const padWithZero = num => num.toString().padStart(2, '0'); const [m1, d1Part, y1] = d1.split('_').map(Number); const [m2, d2Part, y2] = d2.split('_').map(Number); // 拼接成YYYYMMDD格式的字符串 const standardDate1 = `${y1}${padWithZero(m1)}${padWithZero(d1Part)}`; const standardDate2 = `${y2}${padWithZero(m2)}${padWithZero(d2Part)}`; // 字符串直接比较字典序即可 return standardDate1 <= standardDate2; }
这个方法的优势:
- 性能略优(日常业务场景下差异几乎可以忽略)
- 完全避开Date对象的时区相关问题
对你现有方法的优化
如果你想保留自己的拼接数字思路,那必须调整拼接顺序,并且给月、日补零,确保格式统一:
function compareDates(d1, d2){ const padWithZero = num => num.toString().padStart(2, '0'); let parts = d1.split('_'); let d1Num = Number(`${parts[2]}${padWithZero(parts[0])}${padWithZero(parts[1])}`); parts = d2.split('_'); let d2Num = Number(`${parts[2]}${padWithZero(parts[0])}${padWithZero(parts[1])}`); return d1Num <= d2Num; }
调整后拼接顺序为年+月+日,并且补零保证每个部分都是两位,这样数字比较的结果就和日期顺序完全一致了。
总的来说,优先推荐使用Date对象的方案,因为它最省心、最不容易出错;如果有特殊场景限制,再考虑标准化字符串或优化后的数字拼接方法。
内容的提问来源于stack exchange,提问作者Andres SK




