如何用Day.js实现带工作日逻辑的日期列表添加与时长计算?
基于Day.js计算跨工作日预约结束时间并插入工作日列表
核心需求
- 使用Day.js库处理时间计算
- 每日固定工作时段为10:00至18:00
- 从指定预约起始日期叠加时长,若当日工作时间不足,剩余时长顺延至下一个工作日(需跳过所有周日)
- 将预约起始日期和计算得到的结束日期插入到对应工作日的
startDate与endDate之间
示例数据
请求参数
let duration = "20:00:00" // 总时长20小时 let appointmentDate = '2023-01-21T16:00:00-06:00' // 预约起始时间
原始工作日列表(已修正示例中的日期格式错误)
[ { startDate: '2023-01-21T10:00:00-06:00'}, // 周六 { endDate: '2023-01-21T18:00:00-06:00'}, { startDate: '2023-01-23T10:00:00-06:00'}, // 周一 { endDate: '2023-01-23T18:00:00-06:00'}, { startDate: '2023-01-24T10:00:00-06:00'}, // 周二 { endDate: '2023-01-24T18:00:00-06:00'}, { startDate: '2023-01-25T10:00:00-06:00'}, // 周三 { endDate: '2023-01-25T18:00:00-06:00'}, { startDate: '2023-01-26T10:00:00-06:00'}, // 周四 { endDate: '2023-01-26T18:00:00-06:00'}, ]
期望最终结果
[ { startDate: '2023-01-21T10:00:00-06:00'}, // 周六 { appointmentDate: '2023-01-21T16:00:00-06:00'}, // 预约起始时间 { endDate: '2023-01-21T18:00:00-06:00'}, { startDate: '2023-01-23T10:00:00-06:00'}, // 周一 { endDate: '2023-01-23T18:00:00-06:00'}, { startDate: '2023-01-24T10:00:00-06:00'}, // 周二 { endDate: '2023-01-24T18:00:00-06:00'}, { startDate: '2023-01-25T10:00:00-06:00'}, // 周三 { appointmentDate: '2023-01-25T12:00:00-06:00'}, // 预约结束时间(叠加20小时后) { endDate: '2023-01-25T18:00:00-06:00'}, { startDate: '2023-01-26T10:00:00-06:00'}, // 周四 { endDate: '2023-01-26T18:00:00-06:00'}, ]
实现方案与代码示例
核心逻辑
- 计算结束时间:逐天扣除剩余时长,遇到周日直接跳过,直到时长耗尽
- 插入工作日列表:遍历列表,将预约时间插入对应日期的
startDate与endDate之间
完整代码
// 引入Day.js及所需插件 const dayjs = require('dayjs'); require('dayjs/plugin/duration'); require('dayjs/plugin/utc'); dayjs.extend(require('dayjs/plugin/duration')); dayjs.extend(require('dayjs/plugin/utc')); // 计算预约结束时间 function calculateAppointmentEnd(startDateStr, durationStr) { const WORK_START = 10; const WORK_END = 18; const WORK_MINUTES_PER_DAY = (WORK_END - WORK_START) * 60; let remainingDuration = dayjs.duration(durationStr); let currentTime = dayjs(startDateStr); while (remainingDuration.asMinutes() > 0) { // 生成当日工作时段的起止时间 const dayStart = currentTime.hour(WORK_START).minute(0).second(0); const dayEnd = currentTime.hour(WORK_END).minute(0).second(0); let availableMinutes; if (currentTime.isBefore(dayStart)) { // 当前时间早于工作开始,当日可用时长为全天工作时间 availableMinutes = WORK_MINUTES_PER_DAY; currentTime = dayStart; } else if (currentTime.isAfter(dayEnd)) { // 当前时间晚于工作结束,直接跳转到下一个工作日 currentTime = getNextWorkDay(currentTime.add(1, 'day')); continue; } else { // 计算当日剩余可用时长 availableMinutes = dayEnd.diff(currentTime, 'minute'); } if (remainingDuration.asMinutes() <= availableMinutes) { // 剩余时长可在当日完成,直接叠加 currentTime = currentTime.add(remainingDuration); remainingDuration = dayjs.duration(0); } else { // 剩余时长超过当日可用,扣减后跳转下一个工作日 remainingDuration = remainingDuration.subtract(availableMinutes, 'minute'); currentTime = getNextWorkDay(currentTime.add(1, 'day')); } } return currentTime.format('YYYY-MM-DDTHH:mm:ssZ'); } // 获取下一个工作日(跳过周日) function getNextWorkDay(date) { let nextDay = dayjs(date); // Day.js中周日为0,周六为6 while (nextDay.day() === 0) { nextDay = nextDay.add(1, 'day'); } return nextDay; } // 将预约时间插入工作日列表 function insertAppointmentIntoWorkDays(workDays, startApptStr, endApptStr) { const startApptDate = dayjs(startApptStr); const endApptDate = dayjs(endApptStr); const result = []; workDays.forEach(item => { result.push(item); // 仅在遇到startDate时检查是否需要插入预约时间 if ('startDate' in item) { const currentDay = dayjs(item.startDate).format('YYYY-MM-DD'); // 插入预约起始时间 if (currentDay === startApptDate.format('YYYY-MM-DD')) { result.push({ appointmentDate: startApptStr }); } // 插入预约结束时间 if (currentDay === endApptDate.format('YYYY-MM-DD')) { result.push({ appointmentDate: endApptStr }); } } }); return result; } // 测试示例 const duration = "20:00:00"; const appointmentDate = '2023-01-21T16:00:00-06:00'; // 计算结束时间 const endAppointmentDate = calculateAppointmentEnd(appointmentDate, duration); // 插入到工作日列表 const originalWorkDays = [ { startDate: '2023-01-21T10:00:00-06:00'}, { endDate: '2023-01-21T18:00:00-06:00'}, { startDate: '2023-01-23T10:00:00-06:00'}, { endDate: '2023-01-23T18:00:00-06:00'}, { startDate: '2023-01-24T10:00:00-06:00'}, { endDate: '2023-01-24T18:00:00-06:00'}, { startDate: '2023-01-25T10:00:00-06:00'}, { endDate: '2023-01-25T18:00:00-06:00'}, { startDate: '2023-01-26T10:00:00-06:00'}, { endDate: '2023-01-26T18:00:00-06:00'}, ]; const finalWorkDays = insertAppointmentIntoWorkDays(originalWorkDays, appointmentDate, endAppointmentDate); console.log('预约结束时间:', endAppointmentDate); console.log('最终工作日列表:', finalWorkDays);
内容的提问来源于stack exchange,提问作者Alexa
相关产品推荐
相关产品推荐

