65 lines
1.9 KiB
TypeScript
65 lines
1.9 KiB
TypeScript
/**
|
|
* Value Object: TimeWindow
|
|
* Encapsulates the concept of a time window used for presence detection.
|
|
* The default window is 180 seconds (3 minutes), meaning a user is considered
|
|
* "online" if their last heartbeat was within this window.
|
|
*/
|
|
export class TimeWindow {
|
|
/** Default presence detection window: 180 seconds (3 minutes) */
|
|
static readonly DEFAULT_SECONDS = 180;
|
|
|
|
/** Minimum allowed window: 30 seconds */
|
|
static readonly MIN_SECONDS = 30;
|
|
|
|
/** Maximum allowed window: 600 seconds (10 minutes) */
|
|
static readonly MAX_SECONDS = 600;
|
|
|
|
private constructor(private readonly seconds: number) {}
|
|
|
|
static create(seconds: number = TimeWindow.DEFAULT_SECONDS): TimeWindow {
|
|
if (seconds < TimeWindow.MIN_SECONDS) {
|
|
throw new Error(`Time window must be at least ${TimeWindow.MIN_SECONDS} seconds, got ${seconds}`);
|
|
}
|
|
if (seconds > TimeWindow.MAX_SECONDS) {
|
|
throw new Error(`Time window must be at most ${TimeWindow.MAX_SECONDS} seconds, got ${seconds}`);
|
|
}
|
|
if (!Number.isInteger(seconds)) {
|
|
throw new Error('Time window must be an integer number of seconds');
|
|
}
|
|
return new TimeWindow(seconds);
|
|
}
|
|
|
|
/** Create the default 180-second window */
|
|
static default(): TimeWindow {
|
|
return new TimeWindow(TimeWindow.DEFAULT_SECONDS);
|
|
}
|
|
|
|
/** Get the window duration in seconds */
|
|
toSeconds(): number {
|
|
return this.seconds;
|
|
}
|
|
|
|
/** Get the window duration in milliseconds */
|
|
toMilliseconds(): number {
|
|
return this.seconds * 1000;
|
|
}
|
|
|
|
/** Calculate the threshold timestamp (now - window) as Unix epoch seconds */
|
|
getThresholdEpoch(): number {
|
|
return Math.floor(Date.now() / 1000) - this.seconds;
|
|
}
|
|
|
|
/** Calculate the threshold timestamp as a Date */
|
|
getThresholdDate(): Date {
|
|
return new Date(Date.now() - this.toMilliseconds());
|
|
}
|
|
|
|
equals(other: TimeWindow): boolean {
|
|
return this.seconds === other.seconds;
|
|
}
|
|
|
|
toString(): string {
|
|
return `${this.seconds}s`;
|
|
}
|
|
}
|