如何计算日程下次激活的剩余秒数?求更优实现方案
日程激活剩余秒数计算优化问题
我们正试图解决一个看似简单的技术问题,但难以找到优质的代码实现方案:
给定星期数组、分钟数组、开始日期、结束日期、当前时间及时区,计算距离日程下次满足所有激活条件的剩余秒数。
参数说明
- weekdays:数组形式,如
[0,1,2,3,4,5,6](0通常代表周日,6代表周六,具体依定义为准) - minutes:数组形式,如
[0,1,2,...1439](一天共1440分钟,若数组包含7,则00:07-00:08时段日程处于激活状态) - start date:格式为
"YYYY-MM-DD" - end date:格式为
"YYYY-MM-DD" - current time:例如Unix时间戳
- timezone:例如
"America/Vancouver",需考虑时区变更(如夏令时切换)
日程激活条件
- 该时间在指定时区对应的星期属于weekdays数组
- 该时间在指定时区对应的当日分钟数属于minutes数组
- 该时间在指定时区对应的日期处于起止日期之间(包含边界)
我们现有一个基于Luxon的函数,虽能部分运行,但对其正确性存疑,且实现过于复杂,请问是否有更简便的解决方案?
现有代码
// Returns 0 if schedule currently active, otherwise seconds until next active or null if no future active export const checkActive = ({ startDate, endDate, minutes, weekDays, timezone, now = null }) => { const nowAtTimezone = now === null ? DateTime.local().setZone(timezone) : DateTime.fromMillis(new Date(now) / 1).setZone(timezone); // Important: new Date('YYYY-MM-DD') creates the date in UTC, not in local timezone const nowDateObj = new Date(nowAtTimezone.toISODate()); const startDateObj = new Date(startDate); const endDateObj = new Date(endDate === null ? '9999-01-01' : endDate); const nowDateActive = startDateObj <= nowDateObj; const nowMinute = nowAtTimezone.hour * 60 + nowAtTimezone.minute; let startMinuteIdx = nowDateActive ? minutes.findIndex((m) => m >= nowMinute) : 0; for ( // IMPORTANT: date here is always in UTC let date = nowDateActive ? nowDateObj : startDateObj; date <= endDateObj; date.setUTCDate(date.getUTCDate() + 1) ) { if (startMinuteIdx !== -1 && weekDays.includes(date.getUTCDay())) { const datetime = DateTime.fromObject({ year: date.getUTCFullYear(), month: date.getUTCMonth() + 1, day: date.getUTCDate() }, { zone: timezone }); while (startMinuteIdx < minutes.length) { const startMinute = minutes[startMinuteIdx]; const hour = Math.floor(startMinute / 60); const minute = startMinute % 60; const startTime = datetime.set({ hour, minute }); if (startTime.hour === hour && startTime.minute === minute) { return Math.max(startTime.toSeconds() - Math.floor(nowAtTimezone.toSeconds()), 0); } startMinuteIdx += 1; } } startMinuteIdx = 0; } return null; };
测试示例
{ startDate: '2022-10-31', endDate: '2022-10-31', minutes: [ 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449 ], weekDays: [0, 1, 2, 3, 4, 5, 6], timezone: 'Etc/GMT+12' }
当当前时间为'2022-10-31T04:56:57.000Z'时,预期结果为7 * 60 * 60 + 3 * 60 + 3 + 6 * 60 * 60 + 45 * 60 = 49683。
内容的提问来源于stack exchange,提问作者vincent
相关产品推荐
相关产品推荐

