如何在Node.js中实现每月固定周次同星期几的周期性会议支持
支持每月固定周次星期几的周期性会议检查
需求说明
需在现有会议室可用性检查API中新增支持每月第N个固定星期几的周期性会议规则:初始会议为某月第K个星期X(例如6月第二周周一),后续所有月份的第K个星期X均需判定为该会议的占用时段。
解决方案
1. 新增日期工具函数
添加两个工具函数,用于提取日期对应的「星期几」和「当月第几个该星期几」:
// 获取日期是当月的第几个星期几(例如当月第二个周一返回2) function getNthDayOfMonth(date) { const targetDay = date.getDay(); // 0=周日,1=周一...6=周六 const firstDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1); // 计算当月第一个目标星期几的日期 const daysToFirstTarget = ((targetDay - firstDayOfMonth.getDay() + 7) % 7); const firstTargetDate = new Date(firstDayOfMonth); firstTargetDate.setDate(firstDayOfMonth.getDate() + daysToFirstTarget); // 计算当前日期是第几个目标星期几 if (date < firstTargetDate) return 1; // 极端情况:日期早于第一个目标日(仅当月1日为目标日时触发) const daysDiff = Math.floor((date - firstTargetDate) / (1000 * 60 * 60 * 24)); return Math.floor(daysDiff / 7) + 1; } // 获取星期几的数字标识(0=周日,1=周一...6=周六) function getDayOfWeek(date) { return date.getDay(); }
2. 修改API核心逻辑
在原有周期判断分支中,新增对M(每月固定周次)类型的处理:
// API endpoint to retrieve the CSV data (Fetching recurring meetings) app.get('/api/checkAvailability', (req, res) => { const { room, date } = req.query; const results = []; // 日期工具函数 function getNthDayOfMonth(date) { const targetDay = date.getDay(); const firstDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1); const daysToFirstTarget = ((targetDay - firstDayOfMonth.getDay() + 7) % 7); const firstTargetDate = new Date(firstDayOfMonth); firstTargetDate.setDate(firstDayOfMonth.getDate() + daysToFirstTarget); if (date < firstTargetDate) return 1; const daysDiff = Math.floor((date - firstTargetDate) / (1000 * 60 * 60 * 24)); return Math.floor(daysDiff / 7) + 1; } function getDayOfWeek(date) { return date.getDay(); } fs.createReadStream('3meetings.csv') .pipe(csv()) .on('data', (data) => results.push(data)) .on('end', () => { const occupiedSlots = results.filter((meeting) => { if (meeting.room === room && meeting.date <= date) { const interval = meeting.interval.toUpperCase(); const meetingDate = new Date(meeting.date); const targetDate = new Date(date); if (interval === 'D') { const daysDiff = Math.floor((targetDate - meetingDate) / (1000 * 60 * 60 * 24)); return daysDiff % 1 === 0; } else if (interval === 'W') { const daysDiff = Math.floor((targetDate - meetingDate) / (1000 * 60 * 60 * 24)); return daysDiff % 7 === 0; } else if (interval === 'W2') { const daysDiff = Math.floor((targetDate - meetingDate) / (1000 * 60 * 60 * 24)); return daysDiff % 14 === 0; } else if (interval === 'M') { // 匹配规则:星期几一致 + 当月第几个该星期几一致 + 目标日期在初始会议之后 const meetingDay = getDayOfWeek(meetingDate); const meetingNth = getNthDayOfMonth(meetingDate); const targetDay = getDayOfWeek(targetDate); const targetNth = getNthDayOfMonth(targetDate); const monthDiff = (targetDate.getFullYear() - meetingDate.getFullYear()) * 12 + (targetDate.getMonth() - meetingDate.getMonth()); return monthDiff >= 0 && meetingDay === targetDay && meetingNth === targetNth; } } return false; }); res.json({ isAvailable: occupiedSlots.length === 0, ...(occupiedSlots.length > 0 && { occupiedSlots }) }); }); });
3. CSV数据配置
在3meetings.csv中,将每月固定周次的会议interval字段设为M即可,例如:
room,date,interval,title 会议室A,2024-06-04,M,月度团队同步会
关键逻辑说明
getNthDayOfMonth:精准计算目标日期是当月的第几个指定星期几,完全匹配「每月第N个星期X」的需求M类型判断:同时校验星期几、当月周次一致性,以及目标日期的时间先后,避免跨月误判- 兼容原有逻辑:保留对
D(每日)、W(每周)、W2(每两周)类型的支持,不影响现有功能
内容的提问来源于stack exchange,提问作者user19592947
相关产品推荐
相关产品推荐

