本文介绍一种高效方法:通过统计每个日期在预订区间端点(start/end)中出现的次数,自动将出现两次及以上的日期(即同日既有退房又有入住)标记为不可用。
在酒店、短租或日历类应用中,一个常见业务逻辑是:当某天既是前一订单的退房日(end),又是后一订单的入住日(start)时,该天应视为“不可预约”——因为房间需进行清洁、交接等操作,通常不支持当日无缝续住。 这类“同日双事件”(如 2025-07-05 同时作为上单的 end 和下单的 start)需要被精准识别并置为 available: false。
核心思路并非检查日期重叠区间,而是聚焦于端点日期的重复性:只要某个日期在所有 reserved 对象的 start 或 end 字段中出现 ≥2 次,就说明它承载了“交接”语义,应被锁定。
以下是实现该逻辑的简洁、可读性强的方案:
const dates = [/* 31 天日期数组,available 默认 true */];
const reserved = [
{ start: "2025-07-03", end: "2025-07-05" },
{ start: "2025-07-05", end: "2025-07-08" },
{ start: "2025-07-08", end: "2025-07-10" },
{ start: "2025-07-18", end: "2025-07-20" },
{ start: "2025-07-22", end: "2025-07-24" },
{ start: "2025-07-24", end: "2025-07-26" }
];
// 步骤 1:提取所有端点日期(含重复)
const allEndpoints = reserved.flatMap(item => [item.start, item.end]);
// 步骤 2:遍历原始日期数组,标记重复端点
const updatedDates = dates.map(dateObj => {
const date = dateObj.date;
// indexOf 与 lastIndexOf 不等 →
至少出现 2 次
if (allEndpoints.indexOf(date) !== allEndpoints.lastIndexOf(date)) {
return { ...dateObj, available: false };
}
return dateObj;
});
console.log(updatedDates);
// 输出中:'2025-07-05', '2025-07-08', '2025-07-24' 的 available 均为 false✅ 优势说明:
⚠️ 注意事项:
const countMap = new Map(); allEndpoints.forEach(d => countMap.set(d, (countMap.get(d) || 0) + 1)); // 然后用 countMap.get(date) >= 2 判断
总结来说,抓住“端点复用即交接日”这一关键业务特征,用最简逻辑达成精准标记,是此类日历状态管理的最佳实践。