matcher/src/modules/ad/core/domain/calendar-tools.service.ts

126 lines
4.3 KiB
TypeScript

import { ExceptionBase } from '@mobicoop/ddd-library';
import { DateInterval } from './candidate.types';
export class CalendarTools {
/**
* Returns the first date corresponding to a week day (0 based monday)
* within a date range
*/
static firstDate = (weekDay: number, dateInterval: DateInterval): Date => {
if (weekDay < 0 || weekDay > 6)
throw new CalendarToolsException(
new Error('weekDay must be between 0 and 6'),
);
const lowerDateAsDate: Date = new Date(dateInterval.lowerDate);
const higherDateAsDate: Date = new Date(dateInterval.higherDate);
if (lowerDateAsDate.getUTCDay() == weekDay) return lowerDateAsDate;
const nextDate: Date = new Date(lowerDateAsDate);
nextDate.setUTCDate(
lowerDateAsDate.getUTCDate() +
(7 - (lowerDateAsDate.getUTCDay() - weekDay)),
);
if (lowerDateAsDate.getUTCDay() < weekDay) {
nextDate.setUTCMonth(lowerDateAsDate.getUTCMonth());
nextDate.setUTCFullYear(lowerDateAsDate.getUTCFullYear());
nextDate.setUTCDate(
lowerDateAsDate.getUTCDate() + (weekDay - lowerDateAsDate.getUTCDay()),
);
}
if (nextDate <= higherDateAsDate) return nextDate;
throw new CalendarToolsException(
new Error('no available day for the given date range'),
);
};
/**
* Returns the last date corresponding to a week day (0 based monday)
* within a date range
*/
static lastDate = (weekDay: number, dateInterval: DateInterval): Date => {
if (weekDay < 0 || weekDay > 6)
throw new CalendarToolsException(
new Error('weekDay must be between 0 and 6'),
);
const lowerDateAsDate: Date = new Date(dateInterval.lowerDate);
const higherDateAsDate: Date = new Date(dateInterval.higherDate);
if (higherDateAsDate.getUTCDay() == weekDay) return higherDateAsDate;
const previousDate: Date = new Date(higherDateAsDate);
previousDate.setUTCDate(
higherDateAsDate.getUTCDate() - (higherDateAsDate.getUTCDay() - weekDay),
);
if (higherDateAsDate.getUTCDay() < weekDay) {
previousDate.setUTCMonth(higherDateAsDate.getUTCMonth());
previousDate.setUTCFullYear(higherDateAsDate.getUTCFullYear());
previousDate.setUTCDate(
higherDateAsDate.getUTCDate() -
(7 + (higherDateAsDate.getUTCDay() - weekDay)),
);
}
if (previousDate >= lowerDateAsDate) return previousDate;
throw new CalendarToolsException(
new Error('no available day for the given date range'),
);
};
/**
* Returns a date from a date (as a date) and a time (as a string), adding optional seconds
*/
static datetimeWithSeconds = (
date: Date,
time: string,
additionalSeconds = 0,
): Date => {
const datetime: Date = new Date(date);
datetime.setUTCHours(parseInt(time.split(':')[0]));
datetime.setUTCMinutes(parseInt(time.split(':')[1]));
datetime.setUTCSeconds(additionalSeconds);
return datetime;
};
/**
* Returns dates from a day and time based on unix epoch day
* (1970-01-01 is day 4)
* The method returns an array of dates because for edges (day 0 and 6)
* we need to return 2 possibilities : one for the previous week, one for the next week
*/
static epochDaysFromTime = (weekDay: number, time: string): Date[] => {
if (weekDay < 0 || weekDay > 6)
throw new CalendarToolsException(
new Error('weekDay must be between 0 and 6'),
);
switch (weekDay) {
case 0:
return [
new Date(`1969-12-28T${time}:00Z`),
new Date(`1970-01-04T${time}:00Z`),
];
case 1:
return [new Date(`1969-12-29T${time}:00Z`)];
case 2:
return [new Date(`1969-12-30T${time}:00Z`)];
case 3:
return [new Date(`1969-12-31T${time}:00Z`)];
case 5:
return [new Date(`1970-01-02T${time}:00Z`)];
case 6:
return [
new Date(`1969-12-27T${time}:00Z`),
new Date(`1970-01-03T${time}:00Z`),
];
case 4:
default:
return [new Date(`1970-01-01T${time}:00Z`)];
}
};
}
export class CalendarToolsException extends ExceptionBase {
static readonly message = 'Calendar tools error';
public readonly code = 'CALENDAR.TOOLS';
constructor(cause?: Error, metadata?: unknown) {
super(CalendarToolsException.message, cause, metadata);
}
}