diff --git a/src/lib/ae_utils/ae_utils__datetime_format.ts b/src/lib/ae_utils/ae_utils__datetime_format.ts
index 926ed635..a47752d9 100644
--- a/src/lib/ae_utils/ae_utils__datetime_format.ts
+++ b/src/lib/ae_utils/ae_utils__datetime_format.ts
@@ -27,7 +27,11 @@ export const iso_datetime_formatter = function iso_datetime_formatter(
named_format: string = 'datetime_iso_no_seconds', // date_iso, datetime_iso_no_seconds
// Pass true/false to resolve to the correct 12h or 24h variant automatically.
// null (default) leaves named_format unchanged — all existing call sites unaffected.
- use_12h: boolean | null = null
+ use_12h: boolean | null = null,
+ // When true, treats a naive datetime string (no Z / offset) as UTC so dayjs
+ // converts it to local browser time on display. Use for timestamps stored as
+ // UTC in the DB but returned without a timezone indicator.
+ treat_as_utc: boolean = false
) {
// console.log('*** iso_datetime_formatter() ***');
@@ -74,6 +78,12 @@ export const iso_datetime_formatter = function iso_datetime_formatter(
raw_datetime = new Date(); // Get the current datetime if one was not passed.
}
+ // Append 'Z' to naive UTC strings so dayjs converts to local browser time.
+ // Guards against double-appending if the backend ever adds timezone info.
+ if (treat_as_utc && typeof raw_datetime === 'string' && !raw_datetime.match(/Z$|[+-]\d{2}:?\d{2}$/)) {
+ raw_datetime = raw_datetime + 'Z';
+ }
+
if (use_12h !== null) {
named_format = use_12h
? (TO_12H[named_format] ?? named_format)
diff --git a/src/routes/events/[event_id]/(badges)/badges/ae_comp__badge_obj_li.svelte b/src/routes/events/[event_id]/(badges)/badges/ae_comp__badge_obj_li.svelte
index bb7c5608..6a166745 100644
--- a/src/routes/events/[event_id]/(badges)/badges/ae_comp__badge_obj_li.svelte
+++ b/src/routes/events/[event_id]/(badges)/badges/ae_comp__badge_obj_li.svelte
@@ -275,13 +275,13 @@ let visible_badge_obj_li = $derived(
Checked in · {print_count}×
{#if event_badge_obj.print_first_datetime}
·
- {ae_util.iso_datetime_formatter(event_badge_obj.print_first_datetime, 'date_full_no_year')}
- {ae_util.iso_datetime_formatter(event_badge_obj.print_first_datetime, 'time_12_long')}
+ {ae_util.iso_datetime_formatter(event_badge_obj.print_first_datetime, 'date_full_no_year', null, true)}
+ {ae_util.iso_datetime_formatter(event_badge_obj.print_first_datetime, 'time_12_long', null, true)}
{/if}
{#if event_badge_obj.print_last_datetime && event_badge_obj.print_last_datetime !== event_badge_obj.print_first_datetime}
· last print:
- {ae_util.iso_datetime_formatter(event_badge_obj.print_last_datetime, 'date_full_no_year')}
- {ae_util.iso_datetime_formatter(event_badge_obj.print_last_datetime, 'time_12_long')}
+ {ae_util.iso_datetime_formatter(event_badge_obj.print_last_datetime, 'date_full_no_year', null, true)}
+ {ae_util.iso_datetime_formatter(event_badge_obj.print_last_datetime, 'time_12_long', null, true)}
{/if}
@@ -451,11 +451,11 @@ let visible_badge_obj_li = $derived(
Printed {print_count}×
{#if event_badge_obj.print_first_datetime}
·
- {ae_util.iso_datetime_formatter(event_badge_obj.print_first_datetime, 'date_full_no_year')} {ae_util.iso_datetime_formatter(event_badge_obj.print_first_datetime, 'time_12_long')}
+ {ae_util.iso_datetime_formatter(event_badge_obj.print_first_datetime, 'date_full_no_year', null, true)} {ae_util.iso_datetime_formatter(event_badge_obj.print_first_datetime, 'time_12_long', null, true)}
{/if}
{#if event_badge_obj.print_last_datetime && event_badge_obj.print_last_datetime !== event_badge_obj.print_first_datetime}
·
- last print: {ae_util.iso_datetime_formatter(event_badge_obj.print_last_datetime, 'date_full_no_year')} {ae_util.iso_datetime_formatter(event_badge_obj.print_last_datetime, 'time_12_long')}
+ last print: {ae_util.iso_datetime_formatter(event_badge_obj.print_last_datetime, 'date_full_no_year', null, true)} {ae_util.iso_datetime_formatter(event_badge_obj.print_last_datetime, 'time_12_long', null, true)}
{/if}
{/if}
@@ -472,14 +472,18 @@ let visible_badge_obj_li = $derived(
CR:
{ae_util.iso_datetime_formatter(
event_badge_obj.created_on,
- 'datetime_iso_12_no_seconds'
+ 'datetime_iso_12_no_seconds',
+ null,
+ true
)}
UP:
{ae_util.iso_datetime_formatter(
event_badge_obj.updated_on,
- 'datetime_iso_12_no_seconds'
+ 'datetime_iso_12_no_seconds',
+ null,
+ true
)}
@@ -491,7 +495,9 @@ let visible_badge_obj_li = $derived(
{event_badge_obj.print_first_datetime
? ae_util.iso_datetime_formatter(
event_badge_obj.print_first_datetime,
- 'datetime_iso_12_no_seconds'
+ 'datetime_iso_12_no_seconds',
+ null,
+ true
)
: '—'}
@@ -500,7 +506,9 @@ let visible_badge_obj_li = $derived(
{event_badge_obj.print_last_datetime
? ae_util.iso_datetime_formatter(
event_badge_obj.print_last_datetime,
- 'datetime_iso_12_no_seconds'
+ 'datetime_iso_12_no_seconds',
+ null,
+ true
)
: '—'}