Buenas noches. Estoy tratando de capturar todos los viernes, domingos y miércoles entre dos fechas usando Moment.js. No podía entender por qué no captura los días:
Me las arreglé para llegar tan lejos:
const allDays = [0, 3, 5]; function formatToPush(dt_inicio, dt_final, dia, horas) { let start = moment(dt_inicio); let end = moment(dt_final); let result = []; let datas = []; let current = start.clone(); if ((current.day(dia).isSameOrAfter(start)) || (current.day(dia).isSameOrAfter(end)) || (current.day(7 + dia).isSameOrBefore(end))) { result.push(current.clone()); } result.map(m => { horas.map(h => { m.set({ hour: h.split(':')[0], minute: h.split(':')[1], second: 0, millisecond: 0 }); datas.push(m.format('YYYY-MM-DD HH:mm:ss')) }) }); return datas; } let final = []; for (let i in allDays) { final.push(...formatToPush('2021-12-01', '2021-12-10', allDays[i], ["10:00", "16:00", "22:30"])) } console.log(final) <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>¿Alguien puede ayudarme a encontrar el error?
¡Gracias!
La condición de si el día está dentro de los límites siempre se cumple para cualquiera de las dos primeras cláusulas o para ambas. Esto significa que toda la expresión es verdadera sin evaluar la tercera cláusula, que es la que podría establecer la fecha en una de las fechas posteriores que falta. Dado que no está ejecutando esa declaración if en un bucle, solo enviará una fecha a la matriz de resultados.
Un algoritmo más generalizado usaría un bucle.
let current = start.clone(); if (current.day(dia).isSameOrAfter(start) && current.isSameOrBefore(end)) { result.push(current.clone()); } while (current.day(7 + dia).isSameOrAfter(start) && current.isSameOrBefore(end)) { result.push(current.clone()); }Nota: También cambié la conjunción a && porque con el bucle, isAfter siempre sería verdadero. También omití current.day(dia) en la segunda cláusula ya que la primera ya está configurando el día de la semana actual.
Presiona un día ( result.push(current.clone()) ) exactamente una vez, por lo que no puede esperar tener más de una fecha por día. Puede hacer una segunda declaración if con esta condición: (current.day(7 + dia).isSameOrBefore(end)) y presionarla por segunda vez.
Además, en js, cuando se cumple la primera condición en if , las otras no se resuelven.
const allDays = [0, 3, 5]; function formatToPush(dt_inicio, dt_final, dia, horas) { let start = moment(dt_inicio); let end = moment(dt_final); let result = []; let datas = []; let current = start.clone(); if ((current.day(dia).isSameOrAfter(start)) || (current.day(dia).isSameOrAfter(end)) || (current.day(7 + dia).isSameOrBefore(end))) { result.push(current.clone()); } if (current.day(7 + dia).isSameOrBefore(end)) { result.push(current.clone()); } result.map(m => { horas.map(h => { m.set({ hour: h.split(':')[0], minute: h.split(':')[1], second: 0, millisecond: 0 }); datas.push(m.format('YYYY-MM-DD HH:mm:ss')) }) }); return datas; } let final = []; for (let i in allDays) { final.push(...formatToPush('2021-12-01', '2021-12-10', allDays[i], ["10:00", "16:00", "22:30"])) } console.log(final) <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>Aquí hay una alternativa si desea hacer esto en tres sencillas líneas utilizando la API de fecha.
Ofrezco esta alternativa considerando que momentjs tiene más de 17,000 líneas de código en 42k.
Por tu consideración.
const startDate = new Date('2021', '11', '1'); const endDate = new Date('2021', '11', '31'); var tempDate = new Date('2021', '11', '1'); var result = []; while (tempDate.valueOf() !== endDate.valueOf()) { if (/Fri|Sun|Wed/.test(tempDate.toDateString())) result.push(new Date(tempDate)); tempDate.setDate(tempDate.getDate() + 1); } result.forEach(day => console.log(day.toDateString(), day.toISOString().replace("T",' ')));