moment.js最近空闲时段查询函数周二查询结果异常
问题:findNearestFreeSlot函数周二查询结果不符合预期
我编写了一个findNearestFreeSlot函数,接收包含day(星期几)和freeSlots('h:mm a'格式时段数组)的对象数组,目标是返回当前时间之后最近的空闲时段,本周无可用时段则返回"wait for next week"。但周二查询时,预期输出应为"Wed, 12:00 pm",实际却返回"Wed, 4:30 pm"。
原函数代码
function findNearestFreeSlot(slotsArray) { const currentDate = moment(); let nearestDayDiff = Infinity; let nearestSlot = null; for (const daySlots of slotsArray) { const { day, freeSlots } = daySlots; for (const slot of freeSlots) { const slotDateTime = moment(slot, 'h:mm a').day(day); // Check if the slot is on or after the current date if (slotDateTime.isSameOrAfter(currentDate)) { const diffDays = Math.abs(currentDate.diff(slotDateTime, 'days')); if (diffDays < nearestDayDiff || (diffDays === nearestDayDiff && slotDateTime.isBefore(nearestSlot))) { nearestDayDiff = diffDays; nearestSlot = slotDateTime; } } } } return nearestSlot ? nearestSlot.format('ddd, h:mm a') : "wait for next week"; }
测试数组
const freeSlotsArray = [ { day: 'wed', freeSlots: ['12:00 pm', '1:00 pm', '1:30 pm', '2:30 pm', '3:00 pm', '3:30 pm', '4:30 pm', '5:00 pm', '6:30 pm', '7:00 pm'] }, { day: 'sat', freeSlots: ['7:00 am', '7:30 am', '8:00 am', '9:00 am', '10:00 am', '10:30 am', '11:30 am', '12:00 pm', '12:30 pm'] }, { day: 'thu', freeSlots: ['12:00 pm', '1:00 pm', '1:30 pm', '2:30 pm', '4:00 pm', '5:30 pm', '6:30 pm', '7:00 pm'] }, { day: 'mon', freeSlots: ['4:00 pm', '4:30 pm', '6:00 pm', '6:30 pm', '7:30 pm', '8:00 pm', '8:30 pm', '9:30 pm'] }, ]; const nearestFreeSlot = findNearestFreeSlot(freeSlotsArray); console.log(nearestFreeSlot);
问题分析及修复
问题根源
原函数的核心问题在于使用截断整数的天数差进行比较,无法精确区分同一天内不同时段的远近。Math.abs(currentDate.diff(slotDateTime, 'days'))会将不足一天的时间差截断为0,同时用绝对值处理导致无法准确判断时间先后逻辑。此外,用null初始化nearestSlot会增加比较逻辑的复杂度,容易出现判断失误。
修复后的代码
function findNearestFreeSlot(slotsArray) { const now = moment(); // 初始化一个足够远的未来时间,避免null判断问题 let nearestSlot = moment().add(100, 'years'); for (const { day, freeSlots } of slotsArray) { // 获取本周该天的起始时间 const dayStart = moment().day(day).startOf('day'); // 跳过本周已过去的日期 if (dayStart.isBefore(now.startOf('day'))) { continue; } for (const slot of freeSlots) { // 基于当天起始时间构建slot的完整时间 const slotTime = moment(dayStart).set({ hour: moment(slot, 'h:mm a').hour(), minute: moment(slot, 'h:mm a').minute() }); // 仅考虑当前时间之后的slot,并更新最近的时段 if (slotTime.isSameOrAfter(now) && slotTime.isBefore(nearestSlot)) { nearestSlot = slotTime; } } } // 判断是否找到本周可用时段 return nearestSlot.isAfter(moment().add(1, 'week')) ? "wait for next week" : nearestSlot.format('ddd, h:mm a'); }
修复说明
- 精确时间比较:直接通过
isBefore比较moment对象的先后,避免天数差的截断误差。 - 明确日期范围:先判断本周的目标日期是否已过,已过则跳过,确保只处理本周未来的时段。
- 简化初始化:用远未来时间初始化
nearestSlot,无需处理null的特殊情况,逻辑更清晰。 - 可靠的时间构建:基于当天起始时间设置时段的小时和分钟,避免
moment(slot, 'h:mm a').day(day)可能带来的日期歧义。
内容的提问来源于stack exchange,提问作者Aimal Khan
相关产品推荐
相关产品推荐

