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

如何使用Moment.js将含重叠时间范围的数组拆分为非重叠时间组的二维数组

如何用Moment.js拆分重叠时间的日程到无重叠子数组?

嘿,这个问题我之前处理过类似的场景,咱们一步步来搞定它!你说得对,排序是解决这类时间重叠问题的基础,之后的核心是给每个新日程找到一个合适的“无重叠队列”。

首先先提个小细节:你提供的timetable里第二个项的start值多了个0,应该是'2021-11-16T10:00:00',我会在代码里修正这个问题,避免后续时间解析出错。

实现步骤

  1. 按开始时间排序
    先把所有日程按start字段升序排列,这样我们可以按时间顺序处理每个日程,确保前面的日程都是更早开始的。

  2. 维护无重叠子数组队列
    我们需要一个二维数组来存放各个无重叠的子数组。对于每个排序后的日程,遍历现有的子数组:

    • 如果某个子数组的最后一个日程的结束时间 不晚于 当前日程的开始时间,说明可以把当前日程加入这个子数组(不会重叠)。
    • 如果遍历完所有子数组都找不到合适的,就新建一个子数组来存放当前日程。

完整代码实现

const moment = require('moment');

const timetable = [ 
  { class: 'one', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' }, 
  { class: 'two', start: '2021-11-16T10:00:00', end: '2021-11-16T11:00:00' }, // 修正了start的格式错误
  { class: 'three', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' }, 
];

// 步骤1:按开始时间升序排序
const sortedTimetable = timetable.sort((a, b) => {
  const aStart = moment(a.start);
  const bStart = moment(b.start);
  return aStart.isBefore(bStart) ? -1 : 1;
});

// 步骤2:拆分到无重叠子数组
const result = [];
for (const item of sortedTimetable) {
  let added = false;
  // 遍历现有子数组,找可以加入的队列
  for (const group of result) {
    const lastItem = group[group.length - 1];
    // 检查当前item的开始时间是否晚于等于组内最后一个item的结束时间
    if (moment(item.start).isSameOrAfter(lastItem.end)) {
      group.push(item);
      added = true;
      break;
    }
  }
  // 如果没找到合适的队列,新建一个
  if (!added) {
    result.push([item]);
  }
}

console.log(result);

代码说明

  • 排序逻辑:用moment(a.start).isBefore(b.start)来比较两个日程的开始时间,确保数组按时间先后排列。
  • 重叠判断:moment(item.start).isSameOrAfter(lastItem.end)是核心判断——如果当前日程的开始时间和上一个日程的结束时间相同或更晚,就说明两个时间不重叠,可以放在同一组。
  • 效率:这个方法的时间复杂度是O(n²),对于大多数日常的日程数量来说完全够用;如果是超大量数据,可以考虑用更高效的优先队列(最小堆)来优化找合适子数组的过程,但日常场景下上面的实现已经足够简洁好用。

运行这段代码后,输出结果就和你预期的完全一致啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 08:32:32