72 lines
2.2 KiB
TypeScript
72 lines
2.2 KiB
TypeScript
import type { IValueObject } from '@core/shared/domain';
|
|
import { NotificationDomainError } from '../errors/NotificationDomainError';
|
|
|
|
export interface QuietHoursProps {
|
|
startHour: number;
|
|
endHour: number;
|
|
}
|
|
|
|
/**
|
|
* Value Object: QuietHours
|
|
*
|
|
* Encapsulates a daily quiet-hours window using 0-23 hour indices and
|
|
* provides logic to determine whether a given hour falls within the window.
|
|
*
|
|
* Supports both normal ranges (start < end) and overnight ranges (start > end).
|
|
*/
|
|
export class QuietHours implements IValueObject<QuietHoursProps> {
|
|
public readonly props: QuietHoursProps;
|
|
|
|
private constructor(startHour: number, endHour: number) {
|
|
this.props = { startHour, endHour };
|
|
}
|
|
|
|
/**
|
|
* Factory with validation.
|
|
* - Hours must be integers between 0 and 23.
|
|
* - Start and end cannot be equal (would mean a 0-length window).
|
|
*/
|
|
static create(startHour: number, endHour: number): QuietHours {
|
|
QuietHours.assertValidHour(startHour, 'Start hour');
|
|
QuietHours.assertValidHour(endHour, 'End hour');
|
|
|
|
if (startHour === endHour) {
|
|
throw new NotificationDomainError('Quiet hours start and end cannot be the same', 'validation');
|
|
}
|
|
|
|
return new QuietHours(startHour, endHour);
|
|
}
|
|
|
|
private static assertValidHour(value: number, label: string): void {
|
|
if (!Number.isInteger(value)) {
|
|
throw new NotificationDomainError(`${label} must be an integer between 0 and 23`, 'validation');
|
|
}
|
|
if (value < 0 || value > 23) {
|
|
throw new NotificationDomainError(`${label} must be between 0 and 23`, 'validation');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given hour (0-23) lies within the quiet window.
|
|
*/
|
|
containsHour(hour: number): boolean {
|
|
QuietHours.assertValidHour(hour, 'Hour');
|
|
|
|
const { startHour, endHour } = this.props;
|
|
|
|
if (startHour < endHour) {
|
|
// Normal range (e.g., 22:00 to 23:59 is NOT this case, but 1:00 to 7:00 is)
|
|
return hour >= startHour && hour < endHour;
|
|
}
|
|
|
|
// Overnight range (e.g., 22:00 to 07:00)
|
|
return hour >= startHour || hour < endHour;
|
|
}
|
|
|
|
equals(other: IValueObject<QuietHoursProps>): boolean {
|
|
return (
|
|
this.props.startHour === other.props.startHour &&
|
|
this.props.endHour === other.props.endHour
|
|
);
|
|
}
|
|
} |