From eb739a2078981711148ad454b23536651172d7a9 Mon Sep 17 00:00:00 2001 From: fxai Date: Tue, 5 May 2026 14:43:07 +0200 Subject: [PATCH] fix:SQLlite missing timezone 'fix' --- .../components/assessment/ActivityHistoryModal.vue | 3 ++- frontend/src/components/ui/DateTimePicker.vue | 4 ++-- frontend/src/composables/useActivityEvaluation.ts | 5 +++-- frontend/src/utils/dateFormatter.ts | 14 ++++++++++++-- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/assessment/ActivityHistoryModal.vue b/frontend/src/components/assessment/ActivityHistoryModal.vue index dd7f93a..28a2e23 100644 --- a/frontend/src/components/assessment/ActivityHistoryModal.vue +++ b/frontend/src/components/assessment/ActivityHistoryModal.vue @@ -19,6 +19,7 @@ import { } from '@/components/ui/select'; import { activityService } from '@/services/activityService'; import type { ActivityHistoryRead, ActivityRead } from '@/types/utils'; +import { parseServerDate } from '@/utils/dateFormatter'; const props = defineProps<{ open: boolean; @@ -98,7 +99,7 @@ watch(selectedVersionId, (newId) => { const formatDate = (dateString: string) => { try { - const d = new Date(dateString); + const d = parseServerDate(dateString); return ( d.toLocaleDateString() + ' ' + diff --git a/frontend/src/components/ui/DateTimePicker.vue b/frontend/src/components/ui/DateTimePicker.vue index c75dbdd..5f23fe8 100644 --- a/frontend/src/components/ui/DateTimePicker.vue +++ b/frontend/src/components/ui/DateTimePicker.vue @@ -23,7 +23,7 @@ import { SelectValue, } from '@/components/ui/select'; import { usePreferencesStore } from '@/stores/preferences'; -import { formatDateTime, formatDateTimeEditable, parseDateTimeInput } from '@/utils/dateFormatter'; +import { formatDateTime, formatDateTimeEditable, parseDateTimeInput, parseServerDate } from '@/utils/dateFormatter'; const props = defineProps<{ modelValue: string | null | undefined; @@ -42,7 +42,7 @@ const timeValue = ref('00:00'); // Always HH:mm 24h format for internal // Helper: Parse UTC string to components in target timezone function parseToTimezone(utcIsoString: string, timezone?: string) { - const date = new Date(utcIsoString); + const date = parseServerDate(utcIsoString); if (isNaN(date.getTime())) return null; const opts: Intl.DateTimeFormatOptions = { diff --git a/frontend/src/composables/useActivityEvaluation.ts b/frontend/src/composables/useActivityEvaluation.ts index 1318411..5f4febf 100644 --- a/frontend/src/composables/useActivityEvaluation.ts +++ b/frontend/src/composables/useActivityEvaluation.ts @@ -1,6 +1,7 @@ import type { Ref } from 'vue'; import { computed, watch } from 'vue'; import type { ActivityEvaluationUpdate, ActivityRead } from '@/types/utils'; +import { parseServerDate } from '@/utils/dateFormatter'; export type EvalResult = 'PASS' | 'FAIL' | 'N/A'; @@ -9,8 +10,8 @@ export function formatTimeDiff( toTime: string | Date | null | undefined, ): string { if (!fromTime || !toTime) return ''; - const from = new Date(fromTime).getTime(); - const to = new Date(toTime).getTime(); + const from = parseServerDate(fromTime).getTime(); + const to = parseServerDate(toTime).getTime(); if (Number.isNaN(from) || Number.isNaN(to)) return ''; const diffMs = to - from; if (diffMs < 0) return 'N/A (negative)'; diff --git a/frontend/src/utils/dateFormatter.ts b/frontend/src/utils/dateFormatter.ts index cc576c0..85f2702 100644 --- a/frontend/src/utils/dateFormatter.ts +++ b/frontend/src/utils/dateFormatter.ts @@ -7,6 +7,16 @@ export interface FormatOptions { timeFormat?: TimeFormat; } +// Server timestamps without an explicit offset (e.g. SQLite-backed responses) +// must be treated as UTC. JS's Date constructor would otherwise parse them as +// local time. Postgres responses include a "Z" suffix and are passed through. +const HAS_TZ_SUFFIX = /[zZ]|[+-]\d{2}:?\d{2}$/; + +export function parseServerDate(value: string | Date): Date { + if (value instanceof Date) return value; + return new Date(HAS_TZ_SUFFIX.test(value) ? value : `${value}Z`); +} + export function formatDateTime( dateString: string | null | undefined, timezone?: string, @@ -15,7 +25,7 @@ export function formatDateTime( ): string { if (!dateString) return '-'; - const date = new Date(dateString); + const date = parseServerDate(dateString); if (Number.isNaN(date.getTime())) return 'Invalid Date'; const hour12 = timeFormat === 'browser' ? undefined : timeFormat === '12h'; @@ -150,7 +160,7 @@ export function formatDateTimeEditable( timeFormat: TimeFormat = 'browser', ): string { if (!dateString) return ''; - const date = new Date(dateString); + const date = parseServerDate(dateString); if (Number.isNaN(date.getTime())) return ''; const hour12 = timeFormat === 'browser' ? undefined : timeFormat === '12h';