- packages/date-tools: parseDateOnly/formatDateOnly/toDateOnly, getWeekStart/addWeeks/buildCalendarMonth, sur Luxon DateTime (UTC) - packages/shared: WEEK_DAYS/WeekDay, MEALS/Meal (contrat de valeurs documenté pour PlanningItemView.weekDay/.meal, pas encore enforcé en base), getPlanningByDateSchema (validation de forme de ?date=)
47 lines
1.9 KiB
TypeScript
47 lines
1.9 KiB
TypeScript
import { DateTime } from "luxon";
|
|
|
|
// A "date-only" value here always means UTC midnight — Prisma's `@db.Date`
|
|
// columns (`Planning.startDate`/`finishDate`, see apps/api's schema.prisma)
|
|
// carry no time-of-day, so every comparison/computation on them needs to be
|
|
// anchored the same way to stay meaningful. `DateTime` (Luxon) is the
|
|
// in-memory representation everywhere in this package; plain `Date`/ISO
|
|
// `string` only ever appear at the two boundaries that require them —
|
|
// Prisma (`Date`) and URLs/query strings (`string`).
|
|
|
|
/**
|
|
* Parses a strict `YYYY-MM-DD` string into a UTC-midnight {@link DateTime}.
|
|
* Returns `null` for anything that isn't a real calendar date — including a
|
|
* value that's merely shaped right but impossible (e.g. `2026-02-30`),
|
|
* unlike native `Date` which would silently roll it over to March 2nd.
|
|
*/
|
|
export function parseDateOnly(iso: string): DateTime | null {
|
|
const parsed = DateTime.fromISO(iso, { zone: "utc" });
|
|
return parsed.isValid ? parsed.startOf("day") : null;
|
|
}
|
|
|
|
/**
|
|
* Formats a {@link DateTime} back to `YYYY-MM-DD`, the inverse of
|
|
* {@link parseDateOnly}.
|
|
*
|
|
* @throws if `date` is an invalid `DateTime` — every `DateTime` produced by
|
|
* this package's own functions is always valid, so this only fires if a
|
|
* caller constructs one by hand incorrectly.
|
|
*/
|
|
export function formatDateOnly(date: DateTime): string {
|
|
const iso = date.toISODate();
|
|
if (iso === null) {
|
|
throw new Error("Cannot format an invalid DateTime as a date-only string");
|
|
}
|
|
return iso;
|
|
}
|
|
|
|
/**
|
|
* Normalizes a `Date` (e.g. a value read back from Prisma) or a
|
|
* `DateTime` in any zone/with any time-of-day to a UTC-midnight
|
|
* {@link DateTime} — the common representation every other function in
|
|
* this package expects and returns.
|
|
*/
|
|
export function toDateOnly(date: Date | DateTime): DateTime {
|
|
const dateTime = date instanceof DateTime ? date : DateTime.fromJSDate(date, { zone: "utc" });
|
|
return dateTime.toUTC().startOf("day");
|
|
}
|