Skip to content

Commit f6fffc4

Browse files
authored
Merge pull request #15 from CompassSecurity/fix/frontend/sqlite-date
fix:SQLite missing timezone 'fix'
2 parents 5110696 + eb739a2 commit f6fffc4

4 files changed

Lines changed: 19 additions & 7 deletions

File tree

frontend/src/components/assessment/ActivityHistoryModal.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from '@/components/ui/select';
2020
import { activityService } from '@/services/activityService';
2121
import type { ActivityHistoryRead, ActivityRead } from '@/types/utils';
22+
import { parseServerDate } from '@/utils/dateFormatter';
2223
2324
const props = defineProps<{
2425
open: boolean;
@@ -98,7 +99,7 @@ watch(selectedVersionId, (newId) => {
9899
99100
const formatDate = (dateString: string) => {
100101
try {
101-
const d = new Date(dateString);
102+
const d = parseServerDate(dateString);
102103
return (
103104
d.toLocaleDateString() +
104105
' ' +

frontend/src/components/ui/DateTimePicker.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
SelectValue,
2424
} from '@/components/ui/select';
2525
import { usePreferencesStore } from '@/stores/preferences';
26-
import { formatDateTime, formatDateTimeEditable, parseDateTimeInput } from '@/utils/dateFormatter';
26+
import { formatDateTime, formatDateTimeEditable, parseDateTimeInput, parseServerDate } from '@/utils/dateFormatter';
2727
2828
const props = defineProps<{
2929
modelValue: string | null | undefined;
@@ -42,7 +42,7 @@ const timeValue = ref<string>('00:00'); // Always HH:mm 24h format for internal
4242
4343
// Helper: Parse UTC string to components in target timezone
4444
function parseToTimezone(utcIsoString: string, timezone?: string) {
45-
const date = new Date(utcIsoString);
45+
const date = parseServerDate(utcIsoString);
4646
if (isNaN(date.getTime())) return null;
4747
4848
const opts: Intl.DateTimeFormatOptions = {

frontend/src/composables/useActivityEvaluation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Ref } from 'vue';
22
import { computed, watch } from 'vue';
33
import type { ActivityEvaluationUpdate, ActivityRead } from '@/types/utils';
4+
import { parseServerDate } from '@/utils/dateFormatter';
45

56
export type EvalResult = 'PASS' | 'FAIL' | 'N/A';
67

@@ -9,8 +10,8 @@ export function formatTimeDiff(
910
toTime: string | Date | null | undefined,
1011
): string {
1112
if (!fromTime || !toTime) return '';
12-
const from = new Date(fromTime).getTime();
13-
const to = new Date(toTime).getTime();
13+
const from = parseServerDate(fromTime).getTime();
14+
const to = parseServerDate(toTime).getTime();
1415
if (Number.isNaN(from) || Number.isNaN(to)) return '';
1516
const diffMs = to - from;
1617
if (diffMs < 0) return 'N/A (negative)';

frontend/src/utils/dateFormatter.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ export interface FormatOptions {
77
timeFormat?: TimeFormat;
88
}
99

10+
// Server timestamps without an explicit offset (e.g. SQLite-backed responses)
11+
// must be treated as UTC. JS's Date constructor would otherwise parse them as
12+
// local time. Postgres responses include a "Z" suffix and are passed through.
13+
const HAS_TZ_SUFFIX = /[zZ]|[+-]\d{2}:?\d{2}$/;
14+
15+
export function parseServerDate(value: string | Date): Date {
16+
if (value instanceof Date) return value;
17+
return new Date(HAS_TZ_SUFFIX.test(value) ? value : `${value}Z`);
18+
}
19+
1020
export function formatDateTime(
1121
dateString: string | null | undefined,
1222
timezone?: string,
@@ -15,7 +25,7 @@ export function formatDateTime(
1525
): string {
1626
if (!dateString) return '-';
1727

18-
const date = new Date(dateString);
28+
const date = parseServerDate(dateString);
1929
if (Number.isNaN(date.getTime())) return 'Invalid Date';
2030

2131
const hour12 = timeFormat === 'browser' ? undefined : timeFormat === '12h';
@@ -150,7 +160,7 @@ export function formatDateTimeEditable(
150160
timeFormat: TimeFormat = 'browser',
151161
): string {
152162
if (!dateString) return '';
153-
const date = new Date(dateString);
163+
const date = parseServerDate(dateString);
154164
if (Number.isNaN(date.getTime())) return '';
155165

156166
const hour12 = timeFormat === 'browser' ? undefined : timeFormat === '12h';

0 commit comments

Comments
 (0)