83 lines
2.4 KiB
TypeScript
83 lines
2.4 KiB
TypeScript
/**
|
|
* Centralized date-window constants and membership helpers per TZ §4.1.2.
|
|
*
|
|
* All date arguments are "yyyyMMdd" strings (TZ URL date format).
|
|
* Bounds are inclusive on both ends. Day-level comparison (time zeroed).
|
|
*/
|
|
|
|
export const BOARD_WINDOW_DAYS_BACK = 1;
|
|
export const BOARD_WINDOW_DAYS_FORWARD = 14;
|
|
export const SCHEDULE_WINDOW_DAYS_BACK = 1;
|
|
export const SCHEDULE_WINDOW_DAYS_FORWARD = 330;
|
|
export const MAP_WINDOW_DAYS_BACK = 1;
|
|
export const MAP_WINDOW_MONTHS_FORWARD = 6;
|
|
|
|
function today(): Date {
|
|
const d = new Date();
|
|
d.setHours(0, 0, 0, 0);
|
|
return d;
|
|
}
|
|
|
|
function addDays(base: Date, days: number): Date {
|
|
const d = new Date(base);
|
|
d.setDate(d.getDate() + days);
|
|
return d;
|
|
}
|
|
|
|
function addMonths(base: Date, months: number): Date {
|
|
const d = new Date(base);
|
|
d.setMonth(d.getMonth() + months);
|
|
return d;
|
|
}
|
|
|
|
function parseYyyymmdd(s: string): Date | null {
|
|
if (!/^\d{8}$/.test(s)) return null;
|
|
const y = Number(s.slice(0, 4));
|
|
const m = Number(s.slice(4, 6));
|
|
const d = Number(s.slice(6, 8));
|
|
if (m < 1 || m > 12 || d < 1 || d > 31) return null;
|
|
const dt = new Date(y, m - 1, d);
|
|
if (dt.getFullYear() !== y || dt.getMonth() !== m - 1 || dt.getDate() !== d) return null;
|
|
return dt;
|
|
}
|
|
|
|
function inRange(date: Date, min: Date, max: Date): boolean {
|
|
return date.getTime() >= min.getTime() && date.getTime() <= max.getTime();
|
|
}
|
|
|
|
export function boardWindowBounds(): [Date, Date] {
|
|
const base = today();
|
|
return [addDays(base, -BOARD_WINDOW_DAYS_BACK), addDays(base, BOARD_WINDOW_DAYS_FORWARD)];
|
|
}
|
|
|
|
export function scheduleWindowBounds(): [Date, Date] {
|
|
const base = today();
|
|
return [addDays(base, -SCHEDULE_WINDOW_DAYS_BACK), addDays(base, SCHEDULE_WINDOW_DAYS_FORWARD)];
|
|
}
|
|
|
|
export function mapWindowBounds(): [Date, Date] {
|
|
const base = today();
|
|
return [addDays(base, -MAP_WINDOW_DAYS_BACK), addMonths(base, MAP_WINDOW_MONTHS_FORWARD)];
|
|
}
|
|
|
|
export function isInBoardWindow(yyyymmdd: string): boolean {
|
|
const d = parseYyyymmdd(yyyymmdd);
|
|
if (!d) return false;
|
|
const [min, max] = boardWindowBounds();
|
|
return inRange(d, min, max);
|
|
}
|
|
|
|
export function isInScheduleWindow(yyyymmdd: string): boolean {
|
|
const d = parseYyyymmdd(yyyymmdd);
|
|
if (!d) return false;
|
|
const [min, max] = scheduleWindowBounds();
|
|
return inRange(d, min, max);
|
|
}
|
|
|
|
export function isInMapWindow(yyyymmdd: string): boolean {
|
|
const d = parseYyyymmdd(yyyymmdd);
|
|
if (!d) return false;
|
|
const [min, max] = mapWindowBounds();
|
|
return inRange(d, min, max);
|
|
}
|