Si tengo la siguiente matriz de objetos con fechas de inicio y finalización, ¿cómo puedo calcular mejor la cantidad máxima de rangos que se superponen entre sí? Solo quiero el recuento de la mayor cantidad de rangos superpuestos. por ejemplo, mi ejemplo a continuación, el mayor número de rangos superpuestos sería 3.
[ { start_date: '2021-01-01 10:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 08:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 12:00:00', end_date: '2021-01-01 14:00:00'}, { start_date: '2021-01-01 12:30:00', end_date: '2021-01-01 14:30:00'}, { start_date: '2021-01-01 14:00:00', end_date: '2021-01-01 17:30:00'}, ]Dos elementos de la lista se superponen si Math.max(start_1, start_2) < Math.min(end_1, end_2) .
No estoy seguro de su requisito de conteo para la cantidad de segmentos de tiempo superpuestos, pero esto debería llevarlo por el camino correcto.
const list = [ { start_date: '2021-01-01 10:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 08:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 12:00:00', end_date: '2021-01-01 14:00:00'}, { start_date: '2021-01-01 12:30:00', end_date: '2021-01-01 14:30:00'}, { start_date: '2021-01-01 14:00:00', end_date: '2021-01-01 17:30:00'}, ]; // Step 1 : Convert to Date objects const dt_list = list.map((currItem) => { return [new Date(currItem.start_date), new Date(currItem.end_date)]; }); // Map over arrays of Date values const result = dt_list.map((item, index) => { let count = 0; // Count overlaps with remainder of list for (let i=(index + 1); i < dt_list.length; i++) { if (Math.max(item[0], dt_list[i][0]) < Math.min(item[1], dt_list[i][1])) count += 1; } return count; }).reduce((sum, current) => { return sum + current; }, 0); console.log(result); // 3Suponiendo que su formato de fecha sea siempre YYYY-MM-DD hh:mm:ss , puede usar comparaciones de cadenas para comparar la fecha/hora. Si también son posibles otros formatos, sugeriría usar alguna biblioteca como Moment.js .
Puede recorrer los rangos y verificar si cada rango se superpone a otro, como:
const ranges = [ { start_date: '2021-01-01 10:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 08:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 12:00:00', end_date: '2021-01-01 14:00:00'}, { start_date: '2021-01-01 12:30:00', end_date: '2021-01-01 14:30:00'}, { start_date: '2021-01-01 14:00:00', end_date: '2021-01-01 17:30:00'}, ]; let overlaps = 0; for (let i = 0; i < ranges.length; i++) { const range1 = ranges[i]; for (let j = i + 1; j < ranges.length; j++) { const range2 = ranges[j]; if (!(range1.start_date >= range2.end_date || range2.end_date <= range1.start_date || range2.start_date >= range1.end_date || range1.end_date <= range2.start_date)) { console.log(JSON.stringify(ranges[i]) + ' overlaps ' + JSON.stringify(ranges[j])); overlaps++; } } } console.log('Overlaps: ' + overlaps); // Overlaps: 3Puede convertir todas las fechas a marcas de tiempo (segundos desde 1970/01/01) para una mejor comparación. Luego, insértelos todos en una nueva matriz converted_dates[] para usarlos dentro de un bucle doble donde se implementa una declaración condicional para ver si hay una superposición entre cualquiera de los rangos.
Este código debería funcionar con cualquier fecha y en cualquier momento, teniendo en cuenta que, para hacerlo, debe mantener el formato de fecha de la matriz de rango original.
const ranges = [ { start_date: '2021-01-01 10:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 08:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 12:00:00', end_date: '2021-01-01 14:00:00'}, { start_date: '2021-01-01 12:30:00', end_date: '2021-01-01 14:30:00'}, { start_date: '2021-01-01 14:00:00', end_date: '2021-01-01 17:30:00'}, ]; const converted_dates = []; for(let range of ranges){ var start_sliced_date = range.start_date.slice(0,10); var start_sliced_hour = range.start_date.slice(11,19); var end_sliced_date = range.end_date.slice(0,10); var end_sliced_hour = range.end_date.slice(11,19); // Create a date object to use getTime() method let newDate = new Date(start_sliced_date + "T" + start_sliced_hour); let start_timeStamp = newDate.getTime()/1000; newDate = new Date(end_sliced_date + "T" + end_sliced_hour); let end_timeStamp = newDate.getTime()/1000; // Create a new array with the dates converted to timeStamps converted_dates.push({ "start": start_timeStamp, "end": end_timeStamp }); } var count = 0; for(var i = 0; i < converted_dates.length; i++){ let end = converted_dates[i].end; for(var pos = i + 1; pos < converted_dates.length; pos++){ let otherStart = converted_dates[pos].start; // Is there an overlap? if(end>otherStart){ count++, console.log('Overlap of range ' + (i + 1) + ' with ' + (pos + 1)); } } } console.log('Total number of overalped ranges: ' + count);