97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
/**
|
|
* Calendar helpers for the flights-map filter date picker.
|
|
*
|
|
* All dates are treated as date-only (time zero'd) for day-level comparisons.
|
|
* minDate/maxDate form the selectable window; `buildDisabledDates` produces
|
|
* the complement of `availableDays` over that window; `findNextEnabledDate`
|
|
* advances a current selection forward until it lands on an enabled day.
|
|
*
|
|
* Matches Angular `FlightsMapFiltersStateService` calendar behavior.
|
|
*/
|
|
|
|
/** Today with time set to 00:00:00 local. */
|
|
export function today(): Date {
|
|
const d = new Date();
|
|
d.setHours(0, 0, 0, 0);
|
|
return d;
|
|
}
|
|
|
|
/** minDate = today - 1 day (Angular parity). */
|
|
export function getMinDate(): Date {
|
|
const d = today();
|
|
d.setDate(d.getDate() - 1);
|
|
return d;
|
|
}
|
|
|
|
/** maxDate = today + 6 months (Angular parity). */
|
|
export function getMaxDate(): Date {
|
|
const d = today();
|
|
d.setMonth(d.getMonth() + 6);
|
|
return d;
|
|
}
|
|
|
|
/**
|
|
* Every date in [minDate, maxDate] whose yyyymmdd is NOT in `availableDays`.
|
|
* When `availableDays` is empty, every date in the range is disabled.
|
|
*/
|
|
export function buildDisabledDates(
|
|
minDate: Date,
|
|
maxDate: Date,
|
|
availableDays: ReadonlyArray<string>,
|
|
): Date[] {
|
|
const available = new Set(availableDays);
|
|
const disabled: Date[] = [];
|
|
const cursor = new Date(minDate);
|
|
cursor.setHours(0, 0, 0, 0);
|
|
const end = new Date(maxDate);
|
|
end.setHours(0, 0, 0, 0);
|
|
while (cursor.getTime() <= end.getTime()) {
|
|
const key = toYyyymmdd(cursor);
|
|
if (!available.has(key)) disabled.push(new Date(cursor));
|
|
cursor.setDate(cursor.getDate() + 1);
|
|
}
|
|
return disabled;
|
|
}
|
|
|
|
/**
|
|
* Advances `current` day-by-day until it hits a non-disabled date, staying
|
|
* within [minDate, maxDate]. Returns `null` if no enabled date exists.
|
|
* `current` itself is tested first. If `current < minDate`, starts at minDate.
|
|
*/
|
|
export function findNextEnabledDate(
|
|
current: Date,
|
|
disabledDates: ReadonlyArray<Date>,
|
|
minDate: Date,
|
|
maxDate: Date,
|
|
): Date | null {
|
|
const disabledSet = new Set(
|
|
disabledDates.map((d) => {
|
|
const x = new Date(d);
|
|
x.setHours(0, 0, 0, 0);
|
|
return x.getTime();
|
|
}),
|
|
);
|
|
const min = new Date(minDate);
|
|
min.setHours(0, 0, 0, 0);
|
|
const max = new Date(maxDate);
|
|
max.setHours(0, 0, 0, 0);
|
|
|
|
const cursor = new Date(current);
|
|
cursor.setHours(0, 0, 0, 0);
|
|
|
|
if (cursor.getTime() < min.getTime()) cursor.setTime(min.getTime());
|
|
|
|
while (cursor.getTime() <= max.getTime()) {
|
|
if (!disabledSet.has(cursor.getTime())) return new Date(cursor);
|
|
cursor.setDate(cursor.getDate() + 1);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function toYyyymmdd(d: Date): string {
|
|
const y = d.getFullYear().toString();
|
|
const m = (d.getMonth() + 1).toString().padStart(2, "0");
|
|
const day = d.getDate().toString().padStart(2, "0");
|
|
return `${y}${m}${day}`;
|
|
}
|