Use local date-only parsing and formatting across date inputs and filters so clicked dates persist exactly.\n\nVerified with local format, lint, i18n, build, full unit tests, PR E2E, focused date E2E, broad smoke reruns, and GitHub PR checks.
85 lines
2.1 KiB
JavaScript
85 lines
2.1 KiB
JavaScript
const DATE_ONLY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
const DATE_ONLY_PREFIX_PATTERN = /^(\d{4}-\d{2}-\d{2})/;
|
|
|
|
const padDatePart = (value) => String(value).padStart(2, "0");
|
|
|
|
export const isValidDate = (value) => value instanceof Date && !Number.isNaN(value.getTime());
|
|
|
|
export const formatLocalDateOnly = (value = new Date()) => {
|
|
if (typeof value === "string") {
|
|
const directMatch = value.trim().match(DATE_ONLY_PREFIX_PATTERN);
|
|
if (directMatch) {
|
|
return directMatch[1];
|
|
}
|
|
}
|
|
|
|
const date = value instanceof Date ? value : new Date(value);
|
|
if (!isValidDate(date)) {
|
|
return "";
|
|
}
|
|
|
|
return [
|
|
date.getFullYear(),
|
|
padDatePart(date.getMonth() + 1),
|
|
padDatePart(date.getDate()),
|
|
].join("-");
|
|
};
|
|
|
|
export const parseLocalDateOnly = (value) => {
|
|
if (value instanceof Date) {
|
|
return isValidDate(value)
|
|
? new Date(value.getFullYear(), value.getMonth(), value.getDate())
|
|
: new Date(Number.NaN);
|
|
}
|
|
|
|
const stringValue = String(value ?? "").trim();
|
|
const match = DATE_ONLY_PATTERN.exec(stringValue);
|
|
if (match) {
|
|
const year = Number(match[1]);
|
|
const month = Number(match[2]);
|
|
const day = Number(match[3]);
|
|
const parsed = new Date(year, month - 1, day);
|
|
|
|
if (
|
|
parsed.getFullYear() === year
|
|
&& parsed.getMonth() === month - 1
|
|
&& parsed.getDate() === day
|
|
) {
|
|
return parsed;
|
|
}
|
|
|
|
return new Date(Number.NaN);
|
|
}
|
|
|
|
const parsed = new Date(stringValue);
|
|
return isValidDate(parsed)
|
|
? new Date(parsed.getFullYear(), parsed.getMonth(), parsed.getDate())
|
|
: parsed;
|
|
};
|
|
|
|
export const todayLocalDateOnly = () => formatLocalDateOnly(new Date());
|
|
|
|
export const yesterdayLocalDateOnly = () => {
|
|
const yesterday = new Date();
|
|
yesterday.setDate(yesterday.getDate() - 1);
|
|
return formatLocalDateOnly(yesterday);
|
|
};
|
|
|
|
export const startOfLocalDate = (value) => {
|
|
const date = parseLocalDateOnly(value);
|
|
if (!isValidDate(date)) {
|
|
return date;
|
|
}
|
|
date.setHours(0, 0, 0, 0);
|
|
return date;
|
|
};
|
|
|
|
export const endOfLocalDate = (value) => {
|
|
const date = parseLocalDateOnly(value);
|
|
if (!isValidDate(date)) {
|
|
return date;
|
|
}
|
|
date.setHours(23, 59, 59, 999);
|
|
return date;
|
|
};
|