Estoy trabajando en un complemento de calendario que mostraría la descripción general de mi ocupación ordenada de la siguiente manera:
Ahora tengo el evento en el calendario con moment.js , por lo que están formateados de esta manera (ordenados en Fecha de inicio):
let events = [{ name: 'Event A', start: '01-11-2021 00:00', end: '08-11-2021 00:00', },{ name: 'Event C', start: '03-11-2021 00:00', end: '06-11-2021 00:00', },{ name: 'Event E', start: '05-11-2021 00:00', end: '08-11-2021 00:00', },{ name: 'Event D', start: '07-11-2021 00:00', end: '12-11-2021 00:00', },{ name: 'Event B', start: '10-11-2021 00:00', end: '17-11-2021 00:00', },]
La matriz de vista general de ocupación esperada sería algo así como:
let ooArray = [ { // Longest/bottom bar start: '01-11-2021 00:00', end: '17-11-2021 00:00', group: 1 }, { // Middle bar 1 start: '03-11-2021 00:00', end: '08-11-2021 00:00', group: 2 }, { // Middle bar 2 start: '10-11-2021 00:00', end: '12-11-2021 00:00', group: 2 }, { // Top bar 1 start: '05-11-2021 00:00', end: '06-11-2021 00:00', group: 3 }, { // Top bar 2 start: '07-11-2021 00:00', end: '08-11-2021 00:00', group: 3 },]
Honestamente, no tengo idea de cómo agrupar los eventos del calendario para que devuelvan una matriz con las horas de inicio y finalización como resultado del cuadro rojo.
¿Alguien que pueda ayudarme a resolver esto? ¡Gracias!
Según la pregunta actualizada, ordene todas las fechas manteniendo el atributo para el inicio y el final. Procéselos en orden para que la primera fecha (que debe ser un comienzo) comience el nivel 1, que es una sola reserva.
Si la próxima fecha es un final, eso termina la barra. Sin embargo, si la próxima fecha es un comienzo, eso aumenta el nivel (es decir, doble reserva). La siguiente es una implementación, es posible que desee ordenar las barras por nivel o fecha de inicio.
La siguiente función primero obtiene todas las fechas ordenadas en orden ascendente con su tipo: inicio o finalización. Luego procesa cada fecha: las fechas de inicio crean una nueva barra , las fechas de finalización finalizan la barra más reciente. Cuando finaliza, la última barra se abre y se agrega a bars , que es una matriz de barras terminadas.
Esto depende de que los datos de origen sean válidos, es decir, debe comenzar con un inicio y terminar con un final, deben estar en el orden correcto y en igual número.
Una mejora sería garantizar que cuando un inicio y un final tengan la misma fecha, el inicio siempre se clasifique antes del final, de modo que los eventos de duración cero (¿hitos?) no se ordenen de inicio a fin, lo que provocaría una disminución del nivel. antes de que se incremente. Puede haber otros problemas con inicios y finales que tienen la misma fecha y hora, pruebe.
// Parse date in DMY H:m format function parseDMY(s) { let [D, M, Y, H, m] = s.split(/\D/); return new Date(Y, M - 1, D, H, m); } // Format as DD-MM-YYYY HH:mm function formatDate(d) { let z = n => ('0'+n).slice(-2); return `${z(d.getDate())}-${z(d.getMonth()+1)}-${d.getFullYear()} ` + `${z(d.getHours())}:${z(d.getMinutes())}`; } // Generates "occupation" bars function calcBookingLevels(events) { // Get sorted array of [{type, Date}] let dates = events.reduce( (dates, event) => { dates.push({type: 'start', date: parseDMY(event.start)}, {type: 'end', date: parseDMY(event.end)}); return dates; }, []).sort((a, b) => a.date - b.date); // Process dates to get occupation bars with levels let bars = []; let starts = []; let level = 0; dates.forEach(date => { // If it's a start, start a new bar if (date.type == 'start') { let bar = {level: ++level, start: formatDate(date.date)}; starts.push(bar); // Otherwise it's an end, close the most recent bar and // move to bars array } else { let t = starts.pop(); t.end = formatDate(date.date); --level; bars.push(t); } }) return bars; } // Sample data let events = [{ name: 'Event A', start: '01-11-2021 00:00', end: '08-11-2021 00:00', },{ name: 'Event C', start: '03-11-2021 00:00', end: '06-11-2021 00:00', },{ name: 'Event E', start: '05-11-2021 00:00', end: '08-11-2021 00:00', },{ name: 'Event D', start: '07-11-2021 00:00', end: '12-11-2021 00:00', },{ name: 'Event B', start: '10-11-2021 00:00', end: '17-11-2021 00:00', },]; // Run it... console.log(calcBookingLevels(events));
Si las fechas estuvieran en formato AAAA-MM-DD HH:mm, podrían clasificarse como cadenas sin convertirlas en Fechas.
Parece que necesita obtener la diff
en milisegundos y ordenar de mayor a menor. Tendrá que jugar con esto para ver de qué manera se ordena (es posible que deba cambiar la 'a' y la 'b' en la declaración de diff
, ya que no lo ejecuté contra su matriz)
const sortedArray = array.sort((a, b) => a.diff(b))
Con la ayuda de @RobG lo descubrí. Aquí está mi respuesta para las personas interesadas:
// Not needed for answer, but result gave warnings so yeah moment.suppressDeprecationWarnings = true; let newItems = [] let dateArray = [] let events = [{ name: 'Event A', start: '01-11-2021 00:00', end: '08-11-2021 00:00', },{ name: 'Event C', start: '03-11-2021 00:00', end: '06-11-2021 00:00', },{ name: 'Event E', start: '05-11-2021 00:00', end: '08-11-2021 00:00', },{ name: 'Event D', start: '07-11-2021 00:00', end: '12-11-2021 00:00', },{ name: 'Event B', start: '10-11-2021 00:00', end: '17-11-2021 00:00', },] // Make one big array with all start and end dates events.forEach(event=> { dateArray.push({ type: 'start', date: event.start }, { type: 'end', date: event.end }) }) // Sort the dates from first to last dateArray = dateArray.sort((left, right) => { return moment(left.date).diff(moment(right.date)) }) let groupID = -1 // Loop through the array with all dates and add them to a group // based on if the current date is a start or end for (let i = 0; i < dateArray.length; i++) { if (dateArray[i].type === 'start') groupID++ else groupID-- for (let ii = 0; ii <= groupID; ii++) { if (dateArray[i + 1] && !moment(dateArray[i].date).isSame(dateArray[i + 1].date)) { newItems.push({ group: 1, start: dateArray[i].date, end: dateArray[i + 1].date, subgroup: 'sg_' + ii, subgroupOrder: ii }) } } } console.log(newItems)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>