fix - timezone fix

This commit is contained in:
2025-09-20 21:06:35 +05:30
parent 54cfb3508d
commit 2068b6b859

View File

@@ -55,52 +55,109 @@ export function toUTCDate(date: Date): Date {
); );
} }
// ---------- formatUTCDateStringToLocal ----------
/** /**
* Converts a stored UTC date string (e.g. from DB) into a Date object * If `dateStr` is:
* and formats it as local yyyy-MM-dd string for UI use. * - date-only "YYYY-MM-DD" -> returns it unchanged
* - ISO instant/string -> returns the LOCAL calendar date "YYYY-MM-DD" of that instant
*/ */
export function formatUTCDateStringToLocal(dateStr: string): string { export function formatUTCDateStringToLocal(dateStr: string): string {
const localDate = parseLocalDate(dateStr); // will strip the time part if (!dateStr) return "";
return formatLocalDate(localDate); // e.g., "2025-07-15" if (isDateOnlyString(dateStr)) return dateStr;
const d = new Date(dateStr);
if (isNaN(d.getTime())) {
// fallback: strip time part and treat as local date
try {
const maybe = parseLocalDate(dateStr);
return formatLocalDate(maybe);
} catch {
return "";
}
}
return formatLocalDate(d); // uses local fields of the instant
} }
/** /**
* Ensure any date (Date|string) is formatted to ISO string for consistent backend storage. * Frontend-only normalizer.
* If it's already a string, pass through. If it's a Date, convert to ISO. * - Returns "YYYY-MM-DD" string representing the calendar date the user expects.
* - This avoids producing ISO instants that confuse frontend display.
*
* Use this for UI display or for sending date-only values to backend if backend accepts date-only.
*/ */
export function normalizeToISOString(date: Date | string): string { export function normalizeToISOString(date: Date | string): string {
const parsed = parseLocalDate(date); const parsed = parseLocalDate(date); // returns local-midnight-based Date
return parsed.toISOString(); // ensures it always starts from local midnight return formatLocalDate(parsed); // "YYYY-MM-DD"
} }
/** // ---------- helpers ----------
* Formats a date string or Date object into a human-readable "DD Mon YYYY" string. const MONTH_SHORT = [
* Examples: "22 Jul 2025" "Jan",
* "Feb",
* @param dateInput The date as a string (e.g., ISO, YYYY-MM-DD) or a Date object. "Mar",
* @returns A formatted date string. "Apr",
*/ "May",
export const formatDateToHumanReadable = ( "Jun",
dateInput?: string | Date "Jul",
): string => { "Aug",
if (!dateInput) return "N/A"; "Sep",
// Create a Date object from the input. "Oct",
// The Date constructor is quite flexible with various string formats. "Nov",
const date = new Date(dateInput); "Dec",
];
// Check if the date is valid. If new Date() fails to parse, it returns "Invalid Date". function isDateOnlyString(s: string): boolean {
if (isNaN(date.getTime())) { return /^\d{4}-\d{2}-\d{2}$/.test(s);
console.error("Invalid date input provided:", dateInput); }
return "Invalid Date"; // Or handle this error in a way that suits your UI
// ---------- formatDateToHumanReadable ----------
/**
* Frontend-safe: never lets timezone shift the displayed calendar day.
* - "YYYY-MM-DD" strings are shown exactly.
* - Date objects are shown using their calendar fields (getFullYear/getMonth/getDate).
* - ISO/timestamp strings are parsed and shown using UTC date component so they do not flip on client TZ.
*/
export function formatDateToHumanReadable(dateInput?: string | Date): string {
if (!dateInput) return "N/A";
// date-only string -> show as-is
if (typeof dateInput === "string" && isDateOnlyString(dateInput)) {
const parts = dateInput.split("-");
const [y, m, d] = parts;
// Defensive check so TypeScript and runtime are both happy
if (!y || !m || !d) {
console.error("Invalid date-only string:", dateInput);
return "Invalid Date";
}
const day = d.padStart(2, "0");
const monthIndex = parseInt(m, 10) - 1;
const monthName = MONTH_SHORT[monthIndex] ?? "Invalid";
return `${day} ${monthName} ${y}`;
} }
// Use Intl.DateTimeFormat for locale-aware, human-readable formatting. // Date object -> use its calendar fields (no TZ conversion)
return new Intl.DateTimeFormat("en-US", { if (dateInput instanceof Date) {
day: "2-digit", // e.g., "01", "22" if (isNaN(dateInput.getTime())) return "Invalid Date";
month: "short", // e.g., "Jan", "Jul" const dd = String(dateInput.getDate()).padStart(2, "0");
year: "numeric", // e.g., "2023", "2025" const mm = MONTH_SHORT[dateInput.getMonth()];
}).format(date); const yy = dateInput.getFullYear();
}; return `${dd} ${mm} ${yy}`;
}
// Otherwise (ISO/timestamp string) -> parse and use UTC date components
const parsed = new Date(dateInput);
if (isNaN(parsed.getTime())) {
console.error("Invalid date input provided:", dateInput);
return "Invalid Date";
}
const dd = String(parsed.getUTCDate()).padStart(2, "0");
const mm = MONTH_SHORT[parsed.getUTCMonth()];
const yy = parsed.getUTCFullYear();
return `${dd} ${mm} ${yy}`;
}
/** /**
* Convert any OCR numeric-ish value into a number. * Convert any OCR numeric-ish value into a number.
@@ -125,7 +182,9 @@ export function toStr(val: string | number | null | undefined): string {
* Convert OCR date strings like "070825" (MMDDYY) into a JS Date object. * Convert OCR date strings like "070825" (MMDDYY) into a JS Date object.
* Example: "070825" → 2025-08-07. * Example: "070825" → 2025-08-07.
*/ */
export function convertOCRDate(input: string | number | null | undefined): Date { export function convertOCRDate(
input: string | number | null | undefined
): Date {
const raw = toStr(input); const raw = toStr(input);
if (!/^\d{6}$/.test(raw)) { if (!/^\d{6}$/.test(raw)) {
@@ -140,7 +199,6 @@ export function convertOCRDate(input: string | number | null | undefined): Date
return new Date(year, month, day); return new Date(year, month, day);
} }
/** /**
* Format a Date or date string into "HH:mm" (24-hour) string. * Format a Date or date string into "HH:mm" (24-hour) string.
* *
@@ -194,4 +252,3 @@ export function formatLocalTime(
return `${pad2(hours)}:${pad2(minutes)}`; return `${pad2(hours)}:${pad2(minutes)}`;
} }