126 lines
4.3 KiB
TypeScript
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);
|
|
}
|
|
}
|