import { DateTimeRangeComponent, AvailabilityComponent, DateRangeComponent, HourComponent } from '@seed/interfaces/components.dates'; import _ from 'lodash'; import { Interval, DateTime } from 'luxon'; export function checkIfDatesAreInAvailabilities( dates: DateTimeRangeComponent[], availabilities: AvailabilityComponent, options?: { zone: string }, ): boolean { const zone = options?.zone || process.env.TIMEZONE || 'utc'; const intervalsExceptions = getExceptionsIntervalFromAvailabilities(availabilities, zone); let isInException = false; if (intervalsExceptions.length > 0) { isInException = _.some(dates, (d) => { return checkIfDateRangeIsInIntervals(d, intervalsExceptions); }); } const intervalDates = getDatesIntervalFromAvailabilities(availabilities, zone); let isInDates = true; if (intervalDates.length > 0) { isInDates = _.every(dates, (d) => { return checkIfDateRangeIsInIntervals(d, intervalDates); }); } return !isInException && isInDates; } function checkIfDateRangeIsInIntervals(dateR: DateTimeRangeComponent, intervals: Interval[]): boolean { const interval = Interval.fromDateTimes(dateR.startDate, dateR.endDate); return _.some(intervals, (i) => i.overlaps(interval)); } function getExceptionsIntervalFromAvailabilities(availabilities: AvailabilityComponent, zone: string): Interval[] { const exceptions = availabilities.exceptions; const intervalsExceptions: Interval[] = []; // Create all ezxceptions intervals if (exceptions) { exceptions.forEach((e) => { createIntervalFromDatesAndHours(e.dates, zone, e.hours, intervalsExceptions); }); } return intervalsExceptions; } function getDatesIntervalFromAvailabilities(availabilities: AvailabilityComponent, zone: string): Interval[] { const dates = availabilities.dates; const hours = availabilities.hours; const datesExceptions: Interval[] = []; // Create all ezxceptions dates if (dates) { createIntervalFromDatesAndHours(dates, zone, hours, datesExceptions); } return datesExceptions; } function createIntervalFromDatesAndHours(dates: DateRangeComponent, zone: string, hours: HourComponent[] | undefined, datesExceptions: Interval[]) { let dateStart = DateTime.fromJSDate(dates.startDate, { zone }); const dateEnd = DateTime.fromJSDate(dates.endDate, { zone }); if (hours) { while (dateStart < dateEnd) { hours.forEach((h) => { const hStart = parseInt(h.from.split(':')[0]); const mStart = parseInt(h.from.split(':')[1]); const hEnd = parseInt(h.to.split(':')[0]); const mEnd = parseInt(h.to.split(':')[1]); datesExceptions.push( Interval.fromDateTimes(dateStart.set({ hour: hStart, minute: mStart }), dateStart.set({ hour: hEnd, minute: mEnd })), ); }); dateStart = dateStart.plus({ day: 1 }); } // if all day } else { datesExceptions.push(Interval.fromDateTimes(DateTime.fromJSDate(dates.startDate, { zone }), DateTime.fromJSDate(dates.endDate, { zone }))); } }