From e7e49c9110b2ecfc5a11036d97da9b5dcda620d0 Mon Sep 17 00:00:00 2001 From: Hiep Le <69354317+hieptl@users.noreply.github.com> Date: Mon, 1 Dec 2025 20:13:54 +0700 Subject: [PATCH] fix(frontend): AppConversationStartTask timezone display in ui (#11847) --- .../conversation-card-footer.tsx | 2 +- .../start-task-card-footer.tsx | 2 +- .../recent-conversation.tsx | 14 ++++--- frontend/src/utils/format-time-delta.ts | 37 +++++++++++++++++-- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/features/conversation-panel/conversation-card/conversation-card-footer.tsx b/frontend/src/components/features/conversation-panel/conversation-card/conversation-card-footer.tsx index fb77b58242..f44a2f8141 100644 --- a/frontend/src/components/features/conversation-panel/conversation-card/conversation-card-footer.tsx +++ b/frontend/src/components/features/conversation-panel/conversation-card/conversation-card-footer.tsx @@ -39,7 +39,7 @@ export function ConversationCardFooter({ {(createdAt ?? lastUpdatedAt) && (

)} diff --git a/frontend/src/components/features/conversation-panel/start-task-card/start-task-card-footer.tsx b/frontend/src/components/features/conversation-panel/start-task-card/start-task-card-footer.tsx index a2f9bb4036..c5339183d5 100644 --- a/frontend/src/components/features/conversation-panel/start-task-card/start-task-card-footer.tsx +++ b/frontend/src/components/features/conversation-panel/start-task-card/start-task-card-footer.tsx @@ -31,7 +31,7 @@ export function StartTaskCardFooter({ {createdAt && (

)} diff --git a/frontend/src/components/features/home/recent-conversations/recent-conversation.tsx b/frontend/src/components/features/home/recent-conversations/recent-conversation.tsx index 7fcabe2f1f..d86bac55bf 100644 --- a/frontend/src/components/features/home/recent-conversations/recent-conversation.tsx +++ b/frontend/src/components/features/home/recent-conversations/recent-conversation.tsx @@ -67,12 +67,14 @@ export function RecentConversation({ conversation }: RecentConversationProps) { ) : null} - - {formatTimeDelta( - new Date(conversation.created_at || conversation.last_updated_at), - )}{" "} - {t(I18nKey.CONVERSATION$AGO)} - + {(conversation.created_at || conversation.last_updated_at) && ( + + {formatTimeDelta( + conversation.created_at || conversation.last_updated_at, + )}{" "} + {t(I18nKey.CONVERSATION$AGO)} + + )} diff --git a/frontend/src/utils/format-time-delta.ts b/frontend/src/utils/format-time-delta.ts index 8f2425a234..6785d9c845 100644 --- a/frontend/src/utils/format-time-delta.ts +++ b/frontend/src/utils/format-time-delta.ts @@ -1,16 +1,45 @@ +/** + * Parses a date string as UTC if it doesn't have a timezone indicator. + * This fixes the issue where ISO strings without timezone info are interpreted as local time. + * @param dateString ISO 8601 date string + * @returns Date object parsed as UTC + * + * @example + * parseDateAsUTC("2025-12-01T11:53:37.273886"); // Parsed as UTC + * parseDateAsUTC("2025-12-01T11:53:37.273886Z"); // Already has timezone, parsed correctly + * parseDateAsUTC("2025-12-01T11:53:37+00:00"); // Already has timezone, parsed correctly + */ +const parseDateAsUTC = (dateString: string): Date => { + // Check if the string already has a timezone indicator + // Look for 'Z' (UTC), '+' (positive offset), or '-' after the time part (negative offset) + const hasTimezone = + dateString.includes("Z") || dateString.match(/[+-]\d{2}:\d{2}$/) !== null; + + if (hasTimezone) { + // Already has timezone info, parse normally + return new Date(dateString); + } + + // No timezone indicator - append 'Z' to force UTC parsing + return new Date(`${dateString}Z`); +}; + /** * Formats a date into a compact string representing the time delta between the given date and the current date. - * @param date The date to format + * @param date The date to format (Date object or ISO 8601 string) * @returns A compact string representing the time delta between the given date and the current date * * @example * // now is 2024-01-01T00:00:00Z * formatTimeDelta(new Date("2023-12-31T23:59:59Z")); // "1s" - * formatTimeDelta(new Date("2022-01-01T00:00:00Z")); // "2y" + * formatTimeDelta("2023-12-31T23:59:59Z"); // "1s" + * formatTimeDelta("2025-12-01T11:53:37.273886"); // Parsed as UTC automatically */ -export const formatTimeDelta = (date: Date) => { +export const formatTimeDelta = (date: Date | string) => { + // Parse string dates as UTC if needed, or use Date object directly + const dateObj = typeof date === "string" ? parseDateAsUTC(date) : date; const now = new Date(); - const delta = now.getTime() - date.getTime(); + const delta = now.getTime() - dateObj.getTime(); const seconds = Math.floor(delta / 1000); const minutes = Math.floor(seconds / 60);