54 lines
1.9 KiB
TypeScript
54 lines
1.9 KiB
TypeScript
export type AgenticRectificationDatePrecision = "day" | "month" | "quarter" | "year";
|
|
|
|
export type AgenticRectificationDateRange = Readonly<{
|
|
start: string;
|
|
end: string;
|
|
precision: AgenticRectificationDatePrecision;
|
|
label: string;
|
|
}>;
|
|
|
|
function isoDate(year: number, month: number, day: number): string {
|
|
const value = new Date(Date.UTC(year, month - 1, day));
|
|
if (value.getUTCFullYear() !== year || value.getUTCMonth() !== month - 1 || value.getUTCDate() !== day) {
|
|
throw new Error("invalid_calendar_date");
|
|
}
|
|
return value.toISOString().slice(0, 10);
|
|
}
|
|
|
|
function monthEnd(year: number, month: number): string {
|
|
return new Date(Date.UTC(year, month, 0)).toISOString().slice(0, 10);
|
|
}
|
|
|
|
export function dateRangeFromDeclared(
|
|
value: string,
|
|
precision: AgenticRectificationDatePrecision,
|
|
): AgenticRectificationDateRange {
|
|
if (precision === "day") {
|
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) throw new Error("invalid_day");
|
|
const [year, month, day] = value.split("-").map(Number);
|
|
const date = isoDate(year!, month!, day!);
|
|
return { start: date, end: date, precision, label: value };
|
|
}
|
|
if (precision === "month") {
|
|
if (!/^\d{4}-\d{2}$/.test(value)) throw new Error("invalid_month");
|
|
const [year, month] = value.split("-").map(Number);
|
|
const start = isoDate(year!, month!, 1);
|
|
return { start, end: monthEnd(year!, month!), precision, label: value };
|
|
}
|
|
if (precision === "quarter") {
|
|
const matched = /^(\d{4})-Q([1-4])$/.exec(value);
|
|
if (!matched) throw new Error("invalid_quarter");
|
|
const year = Number(matched[1]);
|
|
const firstMonth = (Number(matched[2]) - 1) * 3 + 1;
|
|
return {
|
|
start: isoDate(year, firstMonth, 1),
|
|
end: monthEnd(year, firstMonth + 2),
|
|
precision,
|
|
label: value,
|
|
};
|
|
}
|
|
if (!/^\d{4}$/.test(value)) throw new Error("invalid_year");
|
|
const year = Number(value);
|
|
return { start: isoDate(year, 1, 1), end: isoDate(year, 12, 31), precision, label: value };
|
|
}
|