如何简化TypeScript/Node中基于Moment.js的下次营业时间计算?
计算距离下一个营业时间的简便方案
我在TypeScript/Node项目中用Moment.js,通过const currentTime = moment()获取当前时间,需要计算商家距离下一个营业时间的时长。商家规则是周一至周五9:00-17:00:比如周一晚7点,距离周二9点还有14小时;周六晚9点,距离周一9点则是36小时。
我知道堆一堆if语句能实现,但觉得这是很常见的场景,应该有现成的库或者Moment.js内置方法,找了半天没头绪,想问有没有更简洁的解决办法?
我当前的实现代码
const currentTime = moment(); const opening = moment('9:00am', 'h:mma'); const midnight = moment('12:00am', 'h:mma'); const nineAMNextDay = opening.add(1, 'day'); let timeUntilBusinessHours; if (currentTime.day() === 1 || currentTime.day() === 2 || currentTime.day() === 3 || currentTime.day() === 4) { if (currentTime.isAfter(opening)) { timeUntilBusinessHours = nineAMNextDay.diff(currentTime, 'seconds'); } else { timeUntilBusinessHours = opening.diff(currentTime, 'seconds'); } } else if (currentTime.day() === 5) { if (currentTime.isBefore(opening)) { timeUntilBusinessHours = opening.diff(currentTime, 'seconds'); } else { timeUntilBusinessHours = midnight.diff(currentTime, 'seconds') + 205200; } } else if (currentTime.day() === 6) { timeUntilBusinessHours = midnight.diff(currentTime, 'seconds') + 118800; } else if (currentTime.day() === 0) { timeUntilBusinessHours = midnight.diff(currentTime, 'seconds') + 32400; }
优化方案1:用Moment.js简化逻辑(无需额外库)
原代码存在隐藏问题:opening.add(1, 'day')会直接修改opening对象本身,导致后续判断出错。下面的写法用clone()避免这个问题,同时把逻辑结构化,减少冗余:
import moment from 'moment'; const getTimeUntilNextOpening = (currentTime: moment.Moment): number => { const OPENING_HOUR = 9; const currentDay = currentTime.day(); // 0=周日,1=周一,…,6=周六 let nextOpening: moment.Moment; // 克隆当前时间,避免修改原对象 const todayOpening = currentTime.clone().hour(OPENING_HOUR).minute(0).second(0); switch(currentDay) { case 1: case 2: case 3: case 4: // 周一至周四 nextOpening = currentTime.isBefore(todayOpening) ? todayOpening : todayOpening.add(1, 'day'); break; case 5: // 周五 nextOpening = currentTime.isBefore(todayOpening) ? todayOpening : todayOpening.add(3, 'day'); break; case 6: // 周六 nextOpening = todayOpening.add(2, 'day'); break; default: // 周日 nextOpening = todayOpening.add(1, 'day'); break; } return nextOpening.diff(currentTime, 'seconds'); }; // 使用示例 const currentTime = moment(); const timeUntilBusinessHours = getTimeUntilNextOpening(currentTime);
优化方案2:用专门的营业时间处理库
如果后续可能遇到更复杂的营业时间规则(比如节假日、分时段营业),可以用moment-business-hours这个库,直接配置规则就能自动计算下一个营业时间:
import moment from 'moment'; import 'moment-business-hours'; // 全局配置营业时间:周一至周五9:00-17:00 moment.updateLocale('en', { workinghours: { workingtime: [['09:00', '17:00']], workingdays: [1, 2, 3, 4, 5] // 对应周一到周五 } }); const currentTime = moment(); // 获取下一个营业开始时间 const nextOpening = moment(currentTime).businessAdd(0, 'hours'); const timeUntilBusinessHours = nextOpening.diff(currentTime, 'seconds');
这个库会自动处理跨周末、非工作日的情况,不用自己写日期判断逻辑,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Sabo Boz
相关产品推荐
相关产品推荐

