如何使用JavaScript的Moment.js扣除指定时间片段生成空闲时段数组
时间槽扣除预约时段实现方案
我们需要对现有时间槽数组扣除指定预约时段,最终返回剩余空档时段数组,以下是完整实现:
核心实现逻辑
- 将所有12小时制时间字符串统一转换为当日0点起的总分钟数,做数值运算更便捷
- 解析预约时长,计算出预约的结束时间对应分钟数
- 遍历每个原时间槽,和预约区间做重叠判断,拆分未被占用的区间
- 最后把剩余区间的分钟数转换回
am/pm格式的时间字符串
完整代码实现
// 工具函数:12小时制时间转当日总分钟数 function timeToMinutes(timeStr) { const [time, period] = timeStr.split(' '); let [hours, minutes] = time.split(':').map(Number); if (period === 'pm' && hours !== 12) hours += 12; if (period === 'am' && hours === 12) hours = 0; return hours * 60 + minutes; } // 工具函数:当日总分钟数转12小时制时间 function minutesToTime(minutes) { const hours = Math.floor(minutes / 60); const mins = minutes % 60; const period = hours >= 12 ? 'pm' : 'am'; const displayHours = hours % 12 || 12; return `${displayHours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')} ${period}`; } // 工具函数:解析时长为分钟数 function parseDuration(durationStr) { const num = parseInt(durationStr); if (durationStr.includes('h')) return num * 60; return num; // 默认min单位 } // 主函数:计算剩余空档时间槽 function getAvailableSlots(timeSlots, bookedSlot, duration) { const bookedStart = timeToMinutes(bookedSlot); const bookedEnd = bookedStart + parseDuration(duration); const result = []; for (const slot of timeSlots) { const slotStart = timeToMinutes(slot.from); const slotEnd = timeToMinutes(slot.to); // 预约和当前时间槽完全不重叠,直接保留原时间槽 if (bookedEnd <= slotStart || bookedStart >= slotEnd) { result.push(slot); continue; } // 预约完全覆盖当前时间槽,直接跳过不保留 if (bookedStart <= slotStart && bookedEnd >= slotEnd) { continue; } // 预约覆盖前半段,保留后半段 if (bookedStart <= slotStart && bookedEnd < slotEnd) { result.push({ from: minutesToTime(bookedEnd), to: slot.to }); continue; } // 预约覆盖后半段,保留前半段 if (bookedEnd >= slotEnd && bookedStart > slotStart) { result.push({ from: slot.from, to: minutesToTime(bookedStart) }); continue; } // 预约落在时间槽中间,拆为前后两段 result.push( { from: slot.from, to: minutesToTime(bookedStart) }, { from: minutesToTime(bookedEnd), to: slot.to } ); } return result; }
测试验证
用需求给出的参数测试:
const timeSlots = [{from: '10:00 am', to: '01:00 pm'}]; const bookedSlot = "12:00 pm"; const duration = "30min"; console.log(getAvailableSlots(timeSlots, bookedSlot, duration));
输出结果完全符合预期:
[ {from: '10:00 am', to: '12:00 pm'}, {from: '12:30 pm', to: '01:00 pm'} ]
兼容场景说明
- 预约时段完全落在时间槽外:直接保留原时间槽,无扣除
- 预约时段完全覆盖当前时间槽:当前时间槽被完全扣除,不返回
- 预约仅覆盖时间槽前半段:仅返回后半段剩余时间
- 预约仅覆盖时间槽后半段:仅返回前半段剩余时间
- 预约落在时间槽中间:拆分为前后两段剩余时间
内容的提问来源于stack exchange,提问作者Ahsan Abrar
相关产品推荐
相关产品推荐

