本文介绍在 JavaScript 中判断一组日期是否连续的方法。通过对比直接比较日期的局限性,引出利用时间戳统一处理跨月、跨年及闰年问题的方案。同时提供了去除时分秒毫秒的通用函数封装,确保判断逻辑的严谨性与复用性。
问题背景与初始思路
这是群里一位朋友提出的问题。起初我认为只需判断 day 字段是否相邻即可,但仔细思考后发现这种思路存在严重漏洞。
问题需求
给定5个格式相同的日期字符串,如何判断它们是否代表连续的5天?
我最初的反应是使用 getDay() 获取星期几后排序,再进行前后对比。
然而深入分析后发现该方法完全不可行。例如,本周一下周二虽然 day 相邻,但并非连续的自然日,会导致误判。
此外,该方法还需额外处理跨月、跨年以及闰月等复杂情况,逻辑过于繁琐。
因此,我编写了以下代码来解决这一问题。
基于时间戳的解决方案
让时间戳抹平一切吧
为了避免纠结上述复杂的日期边界问题,我想到利用时间戳。时间戳可以完全忽略日期格式的复杂性,只需将日期转换为时间戳进行比较即可。
基于此思路,我给出了如下代码实现:
let days = [
'2016-02-28',
'2016-02-29', // 闰月
'2016-03-01', // 跨月
'2016-03-02',
'2016-03-03',
]
// 先排序,然后转时间戳
let _days = days.sort().map((d, i) => {
let dt = new Date(d)
dt.setDate(dt.getDate() + 4 - i) // 处理为相同日期
return +dt
})
// 比较时间戳是否一致
console.log(
_days[0] == _days[1] &&
_days[0] == _days[2] &&
_days[0] == _days[3] &&
_days[0] == _days[4]
)
这样一切问题都迎刃而解,无论是跨年、跨月还是闰月,时间戳都能统一处理。
通用函数封装与优化
通用函数封装
上述代码仍存在一定缺陷,因为它没有处理时分秒。如果输入的日期包含时分秒,必须先将其抹去,否则会影响判断结果。
let days = [
'2016-02-28 12:00:00',
'2016-02-29 12:00:01', // 闰月
'2016-03-01 12:00:02', // 跨月
'2016-03-02 12:00:03',
'2016-03-03 12:00:04',
'2016-03-04 12:00:04',
]
console.log(continueDays(days))
function continueDays(arr_days) {
// 先排序,然后转时间戳
let days = arr_days.sort().map((d, i) => {
let dt = new Date(d)
dt.setDate(dt.getDate() + 4 - i) // 处理为相同日期
// 抹去 时 分 秒 毫秒
dt.setHours(0)
dt.setMinutes(0)
dt.setSeconds(0)
dt.setMilliseconds(0)
return +dt
})
let ret = true
days.forEach(d => {
if (days[0] !== d) {
ret = false
}
})
return ret
}
这个函数仅改动了两处:一是抹去时、分、秒和毫秒,二是改为循环比较,其余逻辑保持一致。
总结与建议
小结
JavaScript 处理时间其实非常简单。例如编写日期插件,借助 Date 对象可以很容易实现,但前提是你需要熟悉 Date 的 API。
当然,如果追求极致的简单,PHP 处理日期更为便捷,其内置函数堪称逆天。
以上这篇 js 判断一组日期是否是连续的简单实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。