You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JavaScript的Moment.js扣除指定时间片段生成空闲时段数组

时间槽扣除预约时段实现方案

我们需要对现有时间槽数组扣除指定预约时段,最终返回剩余空档时段数组,以下是完整实现:

核心实现逻辑

  • 将所有12小时制时间字符串统一转换为当日0点起的总分钟数,做数值运算更便捷
  • 解析预约时长,计算出预约的结束时间对应分钟数
  • 遍历每个原时间槽,和预约区间做重叠判断,拆分未被占用的区间
  • 最后把剩余区间的分钟数转换回am/pm格式的时间字符串

完整代码实现

// 工具函数:12小时制时间转当日总分钟数
function timeToMinutes(timeStr) {
  const [time, period] = timeStr.split(' ');
  let [hours, minutes] = time.split(':').map(Number);
  if (period === 'pm' && hours !== 12) hours += 12;
  if (period === 'am' && hours === 12) hours = 0;
  return hours * 60 + minutes;
}

// 工具函数:当日总分钟数转12小时制时间
function minutesToTime(minutes) {
  const hours = Math.floor(minutes / 60);
  const mins = minutes % 60;
  const period = hours >= 12 ? 'pm' : 'am';
  const displayHours = hours % 12 || 12;
  return `${displayHours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')} ${period}`;
}

// 工具函数:解析时长为分钟数
function parseDuration(durationStr) {
  const num = parseInt(durationStr);
  if (durationStr.includes('h')) return num * 60;
  return num; // 默认min单位
}

// 主函数:计算剩余空档时间槽
function getAvailableSlots(timeSlots, bookedSlot, duration) {
  const bookedStart = timeToMinutes(bookedSlot);
  const bookedEnd = bookedStart + parseDuration(duration);
  const result = [];

  for (const slot of timeSlots) {
    const slotStart = timeToMinutes(slot.from);
    const slotEnd = timeToMinutes(slot.to);

    // 预约和当前时间槽完全不重叠,直接保留原时间槽
    if (bookedEnd <= slotStart || bookedStart >= slotEnd) {
      result.push(slot);
      continue;
    }

    // 预约完全覆盖当前时间槽,直接跳过不保留
    if (bookedStart <= slotStart && bookedEnd >= slotEnd) {
      continue;
    }

    // 预约覆盖前半段,保留后半段
    if (bookedStart <= slotStart && bookedEnd < slotEnd) {
      result.push({
        from: minutesToTime(bookedEnd),
        to: slot.to
      });
      continue;
    }

    // 预约覆盖后半段,保留前半段
    if (bookedEnd >= slotEnd && bookedStart > slotStart) {
      result.push({
        from: slot.from,
        to: minutesToTime(bookedStart)
      });
      continue;
    }

    // 预约落在时间槽中间,拆为前后两段
    result.push(
      { from: slot.from, to: minutesToTime(bookedStart) },
      { from: minutesToTime(bookedEnd), to: slot.to }
    );
  }

  return result;
}

测试验证

用需求给出的参数测试:

const timeSlots = [{from: '10:00 am', to: '01:00 pm'}];
const bookedSlot = "12:00 pm";
const duration = "30min";

console.log(getAvailableSlots(timeSlots, bookedSlot, duration));

输出结果完全符合预期:

[
  {from: '10:00 am', to: '12:00 pm'},
  {from: '12:30 pm', to: '01:00 pm'}
]

兼容场景说明

  • 预约时段完全落在时间槽外:直接保留原时间槽,无扣除
  • 预约时段完全覆盖当前时间槽:当前时间槽被完全扣除,不返回
  • 预约仅覆盖时间槽前半段:仅返回后半段剩余时间
  • 预约仅覆盖时间槽后半段:仅返回前半段剩余时间
  • 预约落在时间槽中间:拆分为前后两段剩余时间

内容的提问来源于stack exchange,提问作者Ahsan Abrar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 04:06:03