frontend: show Energy/DSMR/meter times in local timezone, 24h

Backend serializes SQLite-read (naive) UTC datetimes without a Z, so the browser
was parsing them as local time -> the UI effectively showed UTC values.

- New src/utils/datetime.ts: treats a tz-less timestamp as UTC, then formats in
  the browser's local timezone with hour12:false (no AM/PM).
- Applied to Energy tabs (contracts/prices/costs/DSMR), per-device readings &
  trends, and the meter readings table on the Records page.
- CostView Today/This month now use local day boundaries (queries stay UTC ISO).
- Untouched: location/poo (raw Zulu strings), the map, and query-window params.
- Tests are timezone-independent (verified under TZ=America/Los_Angeles).
This commit is contained in:
2026-06-24 13:22:07 +02:00
parent 9d3e28a529
commit effe434637
9 changed files with 301 additions and 37 deletions
+4 -3
View File
@@ -33,6 +33,7 @@ import {
} from './hooks'
import { ContractForm } from './ContractForm'
import apiClient from '../api/client'
import { formatLocalDate } from '../utils/datetime'
// ---------------------------------------------------------------------------
// Version history modal
@@ -96,11 +97,11 @@ function VersionHistoryModal({ contractId, contractName, onClose }: VersionHisto
<Accordion.Control>
<Group gap="sm">
<Text size="sm" fw={500}>
From: {new Date(v.effective_from).toLocaleDateString()}
From: {formatLocalDate(v.effective_from)}
</Text>
{v.effective_to ? (
<Text size="xs" c="dimmed">
To: {new Date(v.effective_to).toLocaleDateString()}
To: {formatLocalDate(v.effective_to)}
</Text>
) : (
<Badge color="green" size="xs">
@@ -195,7 +196,7 @@ function ContractTable({
<Table.Td>{contract.currency}</Table.Td>
<Table.Td>
<Text size="xs" c="dimmed">
{new Date(contract.created_at).toLocaleDateString()}
{formatLocalDate(contract.created_at)}
</Text>
</Table.Td>
<Table.Td>