Files
suaveplan/packages/security-stack/security/license/src/time/time.ts
2026-05-27 23:47:53 +01:00

61 lines
2.0 KiB
TypeScript

import type { Clock } from "@suaveplan/types";
import { MS_PER_DAY } from "../constants/constants.js";
import { TimeEncodingType } from "../types/license.js";
const defaultClock: Clock = () => Date.now();
/**
* Convert a `Date` (or now) to days since the Unix epoch. The 18-bit
* `timeValue` field can hold ~718 years of day numbers.
*/
export function getDayNumber(date?: Date, clock: Clock = defaultClock): number {
const ms = date !== undefined ? date.getTime() : clock();
return Math.floor(ms / MS_PER_DAY);
}
/** Inverse of {@link getDayNumber}. */
export function dayNumberToDate(dayNumber: number): Date {
return new Date(dayNumber * MS_PER_DAY);
}
/**
* Determine whether a license is expired given its time-encoding metadata.
* The optional `clock` defaults to `Date.now()` and is read only when
* `referenceDate` is omitted.
*/
export function checkExpiration(
timeEncodingType: TimeEncodingType,
timeValue: number,
referenceDate?: Date,
creationDate?: Date,
clock: Clock = defaultClock
): { isExpired: boolean; expirationDate?: Date } {
const ref = referenceDate ?? new Date(clock());
switch (timeEncodingType) {
case TimeEncodingType.NONE:
return { isExpired: false };
case TimeEncodingType.ABSOLUTE_DAYS: {
const expirationDate = dayNumberToDate(timeValue);
return { isExpired: ref > expirationDate, expirationDate };
}
case TimeEncodingType.RELATIVE_DAYS: {
const creation = creationDate ?? ref;
const expirationDate = new Date(
creation.getTime() + timeValue * MS_PER_DAY
);
return { isExpired: ref > expirationDate, expirationDate };
}
case TimeEncodingType.ABSOLUTE_TIMESTAMP: {
const expirationDate = new Date(timeValue * 1000);
return { isExpired: ref > expirationDate, expirationDate };
}
default:
return { isExpired: false };
}
}