使用moment检查时间是否重叠?

23

我有一个时间范围数组,形如 [start_time, end_time]

let timeSegments = [];
timeSegments.push(["02:00", "07:00"])
timeSegments.push(["03:00", "04:00"])

这些时间段有重叠,因为 2AM - 7AM 包括 3AM - 4AM

同样地:

let timeSegments = [];
timeSegments.push(["14:00", "18:00"])
timeSegments.push(["15:00", "19:00"])

2PM6PM3PM7PM 重叠。

我正在使用 momentjs 库,并想知道一种确定我的 timeSegments 数组是否包含任何时间段重叠的方法?timeSegments 数组最多可以包含 10 个 [start_time, end_time] 对。谢谢!

我只想知道是否有时间段重叠(true/false),不需要知道哪些时间段重叠等详细信息。


那么你希望结果是什么?如果您的数组中有任何时间重叠,是否为“true”?重叠时间?重叠次数?您的数组是否始终按照您的示例排序(从最早到最晚)? - Jamiec
4个回答

26

您可以使用Array.prototype.sort方法,按照start_time属性对 timeSegments 数组进行排序,并遍历排序后的列表,检查当前时间段的 end_time 是否大于下一个时间段的 start_time

如果出现这种情况,则存在重叠。

以下是一种实现示例:

const checkOverlap = (timeSegments) => {
  if (timeSegments.length === 1) return false;

  timeSegments.sort((timeSegment1, timeSegment2) =>
    timeSegment1[0].localeCompare(timeSegment2[0])
  );

  for (let i = 0; i < timeSegments.length - 1; i++) {
    const currentEndTime = timeSegments[i][1];
    const nextStartTime = timeSegments[i + 1][0];

    if (currentEndTime > nextStartTime) {
      return true;
    }
  }

  return false;
};

const timeSegments1 = [
  ["03:00", "04:00"],
  ["02:00", "07:00"],
  ["12:00", "15:00"]
];

const timeSegments2 = [
  ["05:00", "07:00"],
  ["03:00", "04:00"],
  ["12:00", "15:00"]
];

console.log(checkOverlap(timeSegments1)); // prints true
console.log(checkOverlap(timeSegments2)); // prints false

注意,Array.prototype.sort会改变数组并原地排序。如果你想保留传递给checkOverlap的数组(通常是个好习惯),你可以创建一个timeSegments的副本(例如使用扩展运算符语法):

const sortedTimeSegments = [...timeSegments].sort(...);

17
你可以使用 moment-range 插件。你可以使用 moment.range 函数创建一个范围,将 moment 对象作为输入(使用 moment(String, String) 解析输入字符串)。然后,你可以使用 overlap 方法来检查两个范围是否重叠。
这里是一个实时示例:

window['moment-range'].extendMoment(moment);

let overlap = (timeSegments) => {
  let ret = false;
  let i = 0;
  while( !ret && i<timeSegments.length-1 ){
    let seg1 = timeSegments[i];
    let seg2 = timeSegments[i+1];
    let range1 = moment.range( moment(seg1[0], 'HH:mm'),  moment(seg1[1], 'HH:mm'));
    let range2 = moment.range( moment(seg2[0], 'HH:mm'),  moment(seg2[1], 'HH:mm'));
    if( range1.overlaps(range2) ){
      ret = true;
    }
    i++;
    
    return ret;
  }
};

let timeSegments = [];
timeSegments.push(["02:00", "07:00"])
timeSegments.push(["03:00", "04:00"])
console.log( overlap(timeSegments) ); // true

timeSegments = [];
timeSegments.push(["14:00", "18:00"])
timeSegments.push(["15:00", "19:00"])
console.log( overlap(timeSegments) ); // true

timeSegments = [];
timeSegments.push(["14:00", "18:00"])
timeSegments.push(["19:00", "21:00"])
console.log( overlap(timeSegments) ); // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-range/3.0.3/moment-range.min.js"></script>


如果您有跨越午夜的时间范围,请将该范围拆分为两个范围(例如,22:00-04:00会创建22:00-24:00和00:00-04:00),并对这两个范围进行重叠检查。 - tsauerwein

1
你可以使用 moment 来比较实际的日期并检查它们之间的重叠:
function rangeOverlap(range1, range2, gran = "hour", inc = "[]") {

  const [ start1, end1 ] = range1;
  const [ start2, end2 ] = range2;

  // check range1 is between range2
  const startFirst = start1.isBetween(start2, end2, gran, inc)
  const endFirst = end1.isBetween(start2, end2, gran, inc)

  // check range2 is between range1
  const startLast = start2.isBetween(start1, end1, gran, inc)
  const endLast = end2.isBetween(start1, end1, gran, inc)

  return startFirst || endFirst || startLast || endLast
}

那么,请考虑这个例子:

const range1 = [
  moment("2022-02-22T10:00:00"), // start
  moment("2022-02-23T10:00:00")  // end
]

const range2 = [
  moment("2022-02-22T10:00:00"), // start
  moment("2022-02-23T10:00:00")  // end
]

const overlap = rangeOverlap(range1, range2)
console.log("Overlaps:", overlap)

1
你可以参考以下代码。我在使用核心JavaScript进行编写。
<script>
    var obj = [{ "from": "08:00", "to": "9:01" }, { "from": "18:45", "to": "19:00" }, { "from": "08:00", "to": "09:00" }, { "from": "12:00", "to": "14:00" }];
    obj = sortTime(obj);
    console.log(obj);
    if (checkoverlapping(obj)) {
        alert("yes time overlaps");
    } else {
        alert("No overlapping")
    }

    function sortTime(obj) {
        obj.sort(function (a, b) {
            KeyA = minuteValue(a.from);
            KeyB = minuteValue(b.from);

            if (KeyA < KeyB) return -1;
            else if (KeyA > KeyB) return 1;
            else {
                a = minuteValue(a.to);
                b = minuteValue(b.to);
                if (a < b) return -1;
                if (a > b) return 1;
                return 0
            }
        })
        return obj;
    }

    function minuteValue(time) {
        time = time.split(":");
        return (time[0] * 60) + (time[1] * 1);
    }


    function checkoverlapping(obj) {
        let previous = obj[0], current, overlapping = false;
        for (let i = 1; i < obj.length; i++) {
            current = obj[i]
            if (minuteValue(previous.to) > minuteValue(current.from)) {
                overlapping = true;
                break;
            }
        }
        return overlapping;
    }

</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接