Así que estoy usando la API de Zendesk para obtener el cronograma de una instancia, la API devuelve un objeto que contiene una matriz llamada intervalos que se ve así:
[ { "start_time": 1980, "end_time": 2460 }, { "start_time": 3420, "end_time": 3900 }, { "start_time": 4860, "end_time": 5340 }, { "start_time": 6300, "end_time": 6780 }, { "start_time": 7740, "end_time": 8220 } ]Este ejemplo solo se traduce en minutos de 9 a. m. a 5 p. m. para cada día hábil de la semana, con el valor en minutos desde el comienzo de la semana, que en realidad es la medianoche del domingo (lo que significa que un valor de 720 sería el mediodía del domingo).
Estoy tratando de implementar alguna lógica del lado del servidor que recorra los intervalos y verifique si la hora actual está entre los intervalos para ese día determinado, lo que permite detectar si actualmente está dentro del horario comercial o no.
Estaba pensando que la biblioteca moment.js podría ser útil para esto y he estado jugando con las .startOf('week') y .diff() pero me siguen bloqueando y me temo que podría no ser tan confiable como yo Me gustaría dado que no estoy seguro si el momento comienza la semana en lunes o domingo.
hasta ahora tengo
let isBusinessHours = false; function checkBusinessHours() { intervals.map((interval, key) => { //offset weekdays to match interval keys let currentDay = moment().weekday() -1; //create comparison start & end times based on interval start & end times let startTime = moment().startOf('week').add(interval.start_time, 'minutes'); let endTime = moment().startOf('week').add(interval.end_time, 'minutes'); //check to see if it's business hours if (moment().isBetween(startTime, endTime) && currentDay === key) { isBusinessHours = true; } }) return isBusinessHours; }Pero no estoy seguro de si esta es la mejor manera de verificar esto.
Usar una compensación desde el comienzo del domingo no parece una buena idea cuando se observa el horario de verano. La mayoría de los lugares utilizan el domingo como día de cambio, por lo que en esos días el domingo no dura 24 horas y todas las compensaciones para esa semana serán ± el cambio de horario de verano en minutos.
Ignorando ese problema, es bastante simple convertir una fecha en un desplazamiento: reste el domingo anterior y divida la diferencia por los milisegundos en un minuto. Convertir de un desplazamiento a Fecha es lo contrario: agregue los minutos a una Fecha del domingo anterior, por ejemplo
// Return Date for start of Sunday 00:00 before d function startOfWeek(d = new Date()) { return new Date(d.getFullYear(), d.getMonth(), d.getDate() - d.getDay()); } // Convert a Date to an offset in minutes // from start of previous Sunday function dateToOffset(d = new Date()) { return Math.floor((d - startOfWeek(d)) / 6e4); } // Convert an offset to date, default is current week // Week starts on Sunday function offsetToDate(offset, d = new Date()) { let date = startOfWeek(d); date.setMinutes(offset); return date; } // Examples // Just a helper to format dates function format(d) { return d.toLocaleString('en', { weekday: 'short', hour: '2-digit', hour12: false, minute: '2-digit' }); } // Show current offset let d = new Date(); console.log(`For ${format(d)} the offset is ${dateToOffset(d)}`); // Convert offsets to dates let data = [ { "start_time": 1980, "end_time": 2460 }, { "start_time": 3420, "end_time": 3900 }, { "start_time": 4860, "end_time": 5340 }, { "start_time": 6300, "end_time": 6780 }, { "start_time": 7740, "end_time": 8220 } ]; data.forEach(o => console.log( `Start: ${format(offsetToDate(o.start_time))} ` + `End : ${format(offsetToDate(o.end_time))}` )); // Find out if dates are between a start and end [new Date(2021,10,25,12), // Thu 25 Nov 12:00 new Date(2021,10,27,12), // Sat 25 Nov 12:00 new Date() // Now ].forEach(d => { let offset = dateToOffset(d); console.log( `Is ${format(d)} between a start and end? ` + `${!!data.find(obj => obj.start_time <= offset && obj.end_time > offset)? 'Yes' : 'No'}` ) });Puede obtener el inicio de la semana, luego agregarle los minutos start_time y end_time, lo que le dará el objeto de fecha ajustado, que luego puede usar para comparar con la fecha actual.
Usé date-fns en lugar de moment.js, pero probablemente puedas traducir el código si es necesario.
const { startOfWeek, add, compareAsc, compareDesc } = require("date-fns") const intervals = [ { "start_time": 1980, "end_time": 2460 }, { "start_time": 3420, "end_time": 3900 }, { "start_time": 4860, "end_time": 5340 }, { "start_time": 6300, "end_time": 6780 }, { "start_time": 7740, "end_time": 8220 } ] const startOfWeekDate = startOfWeek(new Date()); const now = new Date(); let isBusinessHour = false; for (let i = 0; i < intervals.length; i++) { const startTime = add(startOfWeekDate, { minutes: intervals[i].start_time }); const endTime = add(startOfWeekDate, { minutes: intervals[i].end_time }); if (compareAsc(now, startTime) === 1 && compareDesc(now, endTime) === 1) { isBusinessHour = true; } } console.log("isBusinessHour", isBusinessHour)Tenga en cuenta que la función startOfWeek acepta un segundo argumento para especificar qué día comienza la semana (generalmente domingo o lunes)