JavaScript检查时间范围是否重叠

ifsvaxew  于 2023-01-01  发布在  Java
关注(0)|答案(7)|浏览(410)

例如,我有一个包含两个对象的数组(类似于myObject 1和myObject 2)。现在,当我添加第三个对象时,我将检查时间范围是否重叠。实际上,我不知道如何才能以高性能的方式做到这一点。
变量myObjectArray = [];

var myObject1 = {};
myObject1.startTime = '08:00';
myObject1.endTime = '12:30';
...

var myObject2 = {};
myObject2.startTime = '11:20';
myObject2.endTime = '18:30';
...

myObjectArray.push(myObject1);
myObjectArray.push(myObject2);
lstz6jyr

lstz6jyr1#

假设我们有一些区间

const INTERVALS = [
  ['14:00', '15:00'],
  ['08:00', '12:30'],
  ['12:35', '12:36'],
  ['13:35', '13:50'],
];

如果我们想添加新的间隔到这个列表中,我们应该检查新的间隔是否不与其中的一些重叠。
您可以循环遍历间隔并检查新间隔是否与其他间隔重叠。注意,在比较间隔时,如果您确定它与您可以将时间转换为数字的日期相同,则不需要Date对象:

function convertTimeToNumber(time) {
  const hours = Number(time.split(':')[0]);
  const minutes = Number(time.split(':')[1]) / 60;
  return hours + minutes;
}

间隔不重叠有两种情况:
1.在(a〈c && a〈d)&&(b〈c && b〈d)之前:

a          b
|----------|
             c          d
             |----------|

1.在(a〉c && a〉d)&&(B〉c & b〉d)之后:

a          b
             |----------|
c          d
|----------|

因为总是c < d,所以可以说不重叠间隔的条件是(a < c && b < c) || (a > d && b > d),并且因为总是a < b,所以可以说这个条件等价于:

b < c || a > d

这个条件的否定应该给予我们一个重叠区间的条件。基于De Morgan's laws,它是:

b >= c && a <= d

请注意,在这两种情况下,间隔不能“接触”对方,这意味着5:00-8:00和8:00-9:00将重叠。如果您想允许它的条件应该是:

b > c && a < d

至少有5种重叠间期的情况需要考虑:
x一个一个七个一个x一个一个八个一个x一个一个九个一个x一个一个十个一个x一个一个
包含额外的添加和排序间隔函数的完整代码如下所示:

const INTERVALS = [
      ['14:00', '15:00'],
      ['08:00', '12:30'],
      ['12:35', '12:36'],
      ['13:35', '13:50'],
    ];

    function convertTimeToNumber(time) {
      const hours = Number(time.split(':')[0]);
      const minutes = Number(time.split(':')[1]) / 60;
      return hours + minutes;
    }

    // assuming current intervals do not overlap
    function sortIntervals(intervals) {
      return intervals.sort((intA, intB) => {
        const startA = convertTimeToNumber(intA[0]);
        const endA = convertTimeToNumber(intA[1]);

        const startB = convertTimeToNumber(intB[0]);
        const endB = convertTimeToNumber(intB[1]);

        if (startA > endB) {
          return 1
        }

        if (startB > endA) {
          return -1
        }

        return 0;
      })
    }

    function isOverlapping(intervals, newInterval) {
      const a = convertTimeToNumber(newInterval[0]);
      const b = convertTimeToNumber(newInterval[1]);

      for (const interval of intervals) {
        const c = convertTimeToNumber(interval[0]);
        const d = convertTimeToNumber(interval[1]);

        if (a < d && b > c) {
          console.log('This one overlap: ', newInterval);
          console.log('with interval: ', interval);
          console.log('----');
          return true;
        }
      }

      return false;
    }

    function isGoodInterval(interval) {
      let good = false;

      if (interval.length === 2) {
        // If you want you can also do extra check if this is the same day
        const start = convertTimeToNumber(interval[0]);
        const end = convertTimeToNumber(interval[1]);

        if (start < end) {
          good = true;
        }
      }

      return good;
    }

    function addInterval(interval) {
      if (!isGoodInterval(interval)) {
        console.log('This is not an interval');
        return;
      }

      if (!isOverlapping(INTERVALS, interval)) {
        INTERVALS.push(interval);

        // you may also want to keep those intervals sorted
        const sortedIntervals = sortIntervals(INTERVALS);
        console.log('Sorted intervals', sortedIntervals);
      }
    }

    // --------------------------------------
    const goodIntervals = [
      ['05:31', '06:32'],
      ['16:00', '17:00'],
      ['12:31', '12:34']
    ];

    let goodCount = 0;
    for (const goodInterval of goodIntervals) {
      if (!isOverlapping(INTERVALS, goodInterval)) {
        goodCount += 1
      }
    }

    console.log('Check good intervals: ', goodCount === goodIntervals.length);

    // --------------------------------------
    const ovelappingIntervals = [
      ['09:30', '12:40'],
      ['05:36', '08:50'],
      ['13:36', '13:37'],
      ['06:00', '20:00'],
      ['14:00', '15:00']
    ]

    let badCount = 0;
    for (const badInterval of ovelappingIntervals) {
      if (isOverlapping(INTERVALS, badInterval)) {
        badCount += 1
      }
    }

    console.log('Check bad intervals: ', badCount === ovelappingIntervals.length);

    // --------------------------------------
    addInterval(goodIntervals[0])
fxnxkyjh

fxnxkyjh2#

你可以试试这样的方法:

var timeList = [];

function addTime() {
  var startTime = document.getElementById("startTime").value;
  var endTime = document.getElementById("endTime").value;

  if (validate(startTime, endTime)){
    timeList.push({
      startTime: startTime,
      endTime: endTime
    });
    print(timeList);
    document.getElementById("error").innerHTML = "";
    }
  else
    document.getElementById("error").innerHTML = "Please select valid time";
}

function validate(sTime, eTime) {
  if (+getDate(sTime) < +getDate(eTime)) {
    var len = timeList.length;
    return len>0?(+getDate(timeList[len - 1].endTime) < +getDate(sTime) ):true;
  } else {
    return false;
  }
}

function getDate(time) {
  var today = new Date();
  var _t = time.split(":");
  today.setHours(_t[0], _t[1], 0, 0);
  return today;
}
function print(data){
  document.getElementById("content").innerHTML = "<pre>" + JSON.stringify(data, 0, 4) + "</pre>";
}
<input type="text" id="startTime" />
<input type="text" id="endTime" />
<button onclick="addTime()">Add Time</button>
<p id="error"></p>

<div id="content"></div>
yftpprvb

yftpprvb3#

moment-jsmoment-range一起使用(引用中断)
测试示例:

const range1 = moment.range(a, c);
const range2 = moment.range(b, d);
range1.overlaps(range2); // true

更多示例请访问https://github.com/rotaready/moment-range#overlaps
注意,要使上面的代码工作,您可能首先要执行以下操作:

<script src="moment.js"></script>
<script src="moment-range.js"></script>

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

HTML代码

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-range/2.2.0/moment-range.min.js"></script>

JavaScript代码

var range  = moment.range(new Date(year, month, day, hours, minutes), new Date(year, month, day, hours, minutes));
var range2 = moment.range(new Date(year, month, day, hours, minutes), new Date(year, month, day, hours, minutes));
range.overlaps(range2); // true or flase

非常简洁的解决方案,momentjs附带了大量的日期和时间实用程序。

uemypmqf

uemypmqf4#

使用JavaScript Date()对象存储时间,然后比较它们。如果object1的结束时间大于object2的开始时间,则它们重叠。您可以使用〉操作符比较它们。

date1.getTime() > date2.getTime()

给出的演示here
Usage of Date object

yqkkidmi

yqkkidmi5#

这有个办法可能管用。

// check if time overlaps with existing times
for (var j = 0; j < times.length; j++) {
        let existing_start_time = moment(this.parseDateTime(this.times[j].start_time)).format();
        let existing_end_time = moment(this.parseDateTime(this.times[j].end_time)).format();

        // check if start time is between start and end time of other times
        if (moment(start_time).isBetween(existing_start_time, existing_end_time)) {
            times[i].error = 'Time overlaps with another time';
            return false;
        }

        // check if end time is between start and end time of other times
        if (moment(end_time).isBetween(existing_start_time, existing_end_time)) {
            times[i].error = 'Time overlaps with another time';
            return false;
        }

}

https://momentjs.com/

4ioopgfo

4ioopgfo6#

您可以通过尝试将时间范围合并到现有时间范围来检查是否存在重叠,如果合并后时间范围的总数减少,则存在重叠。
我发现以下文章可能有助于处理合并范围

ukqbszuj

ukqbszuj7#

要确定时间范围是否与其他时间范围重叠,可以同时使用moment.jsmoment-range库。
首先安装moment-jsmoment-range假定您有一个包含示例对象的INTERVALS数组:

const INTERVALS = [
    { START: 0, END: 10 },
    { START: 12, END: 30 },
    ...
]

您可以使用以下函数:

const validateIntervalOverlaps = () => {
if (INTERVAL_START && INTERVAL__END) {
  const timeInterval = moment.range(moment(INTERVAL_START), moment(INTERVAL_ENDS))

  const overlappingInterval = INTERVALS.find(intervalItem => {
    const interval = moment.range(moment(intervalItem.START), moment(intervalItem.END))
    return timeInterval.overlaps(interval)
  })

  return overlappingInterval
}

}
接下来,你可以对overlappingInterval做你需要做的事情:)fidoe.确定它是否存在或者以任何其他方式使用它。祝你好运!

相关问题