Как найти перекрытие между временными интервалами без даты - PullRequest
1 голос
/ 07 июля 2019

Мне нужно выяснить перекрытие между 2-х временными диапазонами, и оно не включает в себя часть даты в сравнении, а только время, например, range_1 - 9 AM-6PM, а range_2 - 5 PM-8AM. Фактическое время в 24-часовом формате. Я написал решение, которое находит перекрытие, но оно не работает, когда любое время находится в кросс-день / после полуночи, например, 22:00-2AM

.

Оба времени относятся к одному и тому же дню, но мое текущее решение не работает должным образом, когда сравнение должно проводиться в любое время после полуночи. Например, он дает правильный выходной сигнал в случае range_1: 9 AM-6PM и range_2: 5 PM-8PM, дает правильное перекрытие выходных 5 PM-6PM, но не может найти перекрытие в случае range_1: 10 PM-2AM и range_2: 1 AM-3AM в тот же день. Ниже приведена ссылка на мой кодовый блок:

https://codepen.io/anon/pen/NZOqJm?editors=0010

    function overlap(t1,t2)
    {
    var timeFormat = "hh:mm";
    let t1from = moment(t1.timeFrom,timeFormat);
    let t1to = moment(t1.timeTo,timeFormat);

    let t2from = moment(t2.timeFrom,timeFormat);
    let t2to = moment(t2.timeTo,timeFormat);

    let overlapFrom = null;
    let overlapTo = null;


    if (t2from.isBetween(t1from, t1to) && t2to.isBetween(t1from, t1to)) {
        //complete overlap
        overlapFrom = t2from;
        overlapTo = t2to;
    }
  else if (t1from.isBetween(t2from, t2to) && t1to.isBetween(t2from, t2to))
    {
       overlapFrom = t1from;
        overlapTo = t1to;
    }
    else if (t2from.isBetween(t1from, t1to)) {
        overlapFrom = t2from;
        overlapTo = t1to;
    }
    else if (t2to.isBetween(t1from, t1to)) {
        overlapFrom = t1from;
        overlapTo = t2to;
    }            

    let doesOverlap = overlapFrom !== null && overlapTo !== null;
    let response = {
        doesOverlap: doesOverlap,
        overlapingMinutes: doesOverlap ?  Math.abs(moment.duration(overlapFrom.diff(overlapTo)).asMinutes()): 0,
        overlapFrom,
        overlapTo
    }
    return response;

    }


/*let t1 = {
  timeFrom:'22:00',
  timeTo:'02:00'
}


let t2 = {
  timeFrom:'01:00',
  timeTo:'03:00'
}*/


let t1 = {
  timeFrom:'09:00',
  timeTo:'18:00'
}


let t2 = {
  timeFrom:'17:00',
  timeTo:'20:00'
}
console.log(overlap(t1,t2));

range_1: 10 PM-2AM

range_2: 1 AM-3AM

Правильный вывод должен быть: с 1:00 до 2:00

Поскольку оба времени совпадают, все время в течение дня и не включает в себя какую-либо дату. Считайте, что в это время каждый день учатся 2 ученика, а затем, когда они перекрываются

Ответы [ 2 ]

0 голосов
/ 08 июля 2019

Есть ряд угловых случаев, которые нужно разобрать, например, сделать «10:00, 11:00» и «11:00, 12:00» перекрываются? И "10:00, 10:00" ноль минут или 24 часа?

В любом случае, я бы сделал так, чтобы преобразовать время в минуты после полуночи и сравнить это. Это то, что делает этот код. Сравнение «время начала одной продолжительности» между «временем начала / окончания другой», и, если нет, поменяйте местами время и повторите проверку.

function overlap(t0, t1) {
    // convert time to minutes past midnight
    var minutes = (d) => {return Object.values(d).map(d => {
        d=d.split(':').map(d=>parseInt(d));
        return d[0]*60+d[1];
    })};
    // If the end time is before the start then add 24 hours to the end
    // time to wrap it into next day. start==end gets 24 hrs added.
    var nextday = (d) => {if(d[0]>=d[1])d[1]+=24*60;return d}
    t0 = nextday(minutes(t0));
    t1 = nextday(minutes(t1));
    var olap = (t0, t1) => {
        // beginning of t0 between begin/end of t1
        // or
        // end of t0 between begin/end of t1
        return (t0[0]>=t1[0] && t0[0]<=t1[1]) 
            || (t1[0]>=t0[0] && t1[0]<=t0[1]);
    }
    return olap(t0, t1) || olap(t1, t0)
}
0 голосов
/ 07 июля 2019

Я бы просто работал с часами / минутами, тогда:

const smaller = (a, b) => a.hours < b.hours || (a.hours === b.hours && a.mins < b.mins);
const equals = (a, b) => a.hours === b.hours && a.mins === b.mins;

function overlap(a, b) {
  if(smaller(a.to, a.from)) {
    return [
      ...overlap({ from: { hours: 0, mins: 0}, to: a.to }, b),
      ...overlap({ from: a.from, to: { hours: 24, mins: 0 }}, b),
    ];
  }
  
  if(smaller(b.to, b.from)) {
    return [
      ...overlap(a, { from: { hours: 0, mins: 0}, to: a.to }),
      ...overlap(a, { from: a.from, to: { hours: 24, mins: 0 }}),
    ];
  }


  const result = {
    from: smaller(b.from, a.from) ? a.from : b.from,
    to: smaller(a.to, b.to) ? a.to : b.to,
  };
  
  return equals(result.from, result.to) ? [] : [result];
}




console.log(...[
  [
    { from: { hours: 6, mins: 10 }, to: { hours: 8, mins: 10 }},
    { from: { hours: 6, mins: 10 }, to: { hours: 8, mins: 10 }}
  ],  [
    { from: { hours: 7, mins: 10 }, to: { hours: 10, mins: 10 }},
    { from: { hours: 6, mins: 10 }, to: { hours: 8, mins: 10 }}
  ],  [
    { from: { hours: 23, mins: 10 }, to: { hours: 8, mins: 10 }},
    { from: { hours: 6, mins: 10 }, to: { hours: 8, mins: 10 }}
  ]
].map(([a, b]) => `${JSON.stringify(a)}\n overlaps with ${JSON.stringify(b)}\n in ${JSON.stringify(overlap(a, b))}\n\n`));
 
...