如何优化date-fns取餐时段生成函数以适配营业时间规则?
优化预点餐应用的取餐时段生成函数
需求背景
开发预点餐应用时,取餐时间需满足以下规则:
- 按指定分钟间隔(如20分钟)生成可选时段
- 仅在商家营业时段内生成:午市12:00-14:00、晚市16:30-21:30
- 周日商家不开放午市,其余日期正常开放午市和晚市
现有代码使用date-fns实现基础功能,但硬编码结束时间,需优化适配上述规则,且希望单次生成所有时段并标记可用性,而非分两次生成午/晚市数组。
优化后的实现代码
import { addMinutes, set, getDay, isWithinInterval, format } from "date-fns"; // 抽离营业时段配置,周日(0)单独处理 const BUSINESS_HOURS = { default: [ { start: { hours: 12, minutes: 0 }, end: { hours: 14, minutes: 0 } }, // 午市 { start: { hours: 16, minutes: 30 }, end: { hours: 21, minutes: 30 } } // 晚市 ], sunday: [ { start: { hours: 16, minutes: 30 }, end: { hours: 21, minutes: 30 } } // 仅晚市 ] }; const generateAvailableTimeSlots = (slotSizeInMinutes: number) => { const now = new Date(); const dayOfWeek = getDay(now); // 0=周日,1-6=周一至周六 const todayBusinessHours = dayOfWeek === 0 ? BUSINESS_HOURS.sunday : BUSINESS_HOURS.default; // 计算当前时间之后的第一个有效间隔时段 let firstAvailableSlot = now; const minutesSinceHour = now.getMinutes(); const remainder = minutesSinceHour % slotSizeInMinutes; if (remainder !== 0) { firstAvailableSlot = addMinutes(now, slotSizeInMinutes - remainder); } else { // 若当前刚好是间隔点,需往后推一个时段避免选择"现在" firstAvailableSlot = addMinutes(firstAvailableSlot, slotSizeInMinutes); } // 获取当天营业结束时间 const lastBusinessPeriod = todayBusinessHours[todayBusinessHours.length - 1]; const endOfBusinessDay = set(now, lastBusinessPeriod.end); const timeSlots = []; let currentSlot = firstAvailableSlot; while (currentSlot <= endOfBusinessDay) { // 判断当前时段是否落在任意营业区间内 const isAvailable = todayBusinessHours.some(period => { const businessStart = set(now, period.start); const businessEnd = set(now, period.end); return isWithinInterval(currentSlot, { start: businessStart, end: businessEnd }); }); timeSlots.push({ timestamp: currentSlot, displayText: format(currentSlot, "HH:mm"), isAvailable }); currentSlot = addMinutes(currentSlot, slotSizeInMinutes); } return timeSlots; }; export default generateAvailableTimeSlots;
关键优化说明
- 配置化营业规则:把不同日期的营业时段抽成可配置对象,后续修改营业时间无需改动核心逻辑
- 单次循环生成所有时段:从最早可预约时间到营业结束时间,逐个生成时段并同步判断可用性,避免分两次处理午/晚市
- 周日特殊逻辑自动适配:通过
getDay获取星期数,自动切换周日的营业时段配置 - 可用性标记清晰:每个时段对象包含
isAvailable字段,前端可直接根据该字段控制下拉框的可选状态(比如灰置不可用选项)
内容的提问来源于stack exchange,提问作者chinds
相关产品推荐
相关产品推荐

