Compare commits
1 Commits
32331d4cf8
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 0314e87c3f |
@ -1,137 +0,0 @@
|
|||||||
Format timestamps as Asia/Dushanbe (UTC+5)
|
|
||||||
|
|
||||||
SQLite stores all timestamps as UTC via datetime('now'). The UI was
|
|
||||||
rendering them raw (e.g. "2026-05-18 15:42:03"), which is 5 hours
|
|
||||||
behind local time for Tajikistan.
|
|
||||||
|
|
||||||
Add formatTs() to the i18n store alongside formatMoney/localized.
|
|
||||||
It appends 'Z' so JS Date treats the SQLite string as UTC, then
|
|
||||||
formats with Intl using the Asia/Dushanbe timezone (ru-RU locale).
|
|
||||||
|
|
||||||
Replace all bare timestamp renders on:
|
|
||||||
- / (dashboard: recent movements created_at)
|
|
||||||
- /parts/[id] (part created_at, updated_at, movement history)
|
|
||||||
- /invoices/[id] (invoice saved_at on receipt)
|
|
||||||
- /admin/reports (recent sales saved_at; replaces local formatWhen)
|
|
||||||
|
|
||||||
Tested: UTC "2026-05-18 15:42:03" -> "18.05.2026, 20:42" (pass)
|
|
||||||
UTC "2026-05-18 00:30:00" -> "18.05.2026, 05:30" (pass)
|
|
||||||
null/empty/invalid input handled gracefully (pass)
|
|
||||||
|
|
||||||
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
||||||
---
|
|
||||||
src/lib/i18n/store.js | 15 +++++++++++++++
|
|
||||||
src/routes/+page.svelte | 2 +-
|
|
||||||
src/routes/admin/reports/+page.svelte | 9 +--------
|
|
||||||
src/routes/invoices/[id]/+page.svelte | 2 +-
|
|
||||||
src/routes/parts/[id]/+page.svelte | 4 ++--
|
|
||||||
5 files changed, 20 insertions(+), 12 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib/i18n/store.js b/src/lib/i18n/store.js
|
|
||||||
--- a/src/lib/i18n/store.js
|
|
||||||
+++ b/src/lib/i18n/store.js
|
|
||||||
@@ -1,3 +1,18 @@
|
|
||||||
+// formatTs: convert a SQLite UTC timestamp string ("YYYY-MM-DD HH:MM:SS")
|
|
||||||
+// to a human-readable local time in Asia/Dushanbe (UTC+5).
|
|
||||||
+// The appended 'Z' is critical — without it JS parses as local time.
|
|
||||||
+export function formatTs(utcStr) {
|
|
||||||
+ if (!utcStr) return '';
|
|
||||||
+ const d = new Date(utcStr.replace(' ', 'T') + 'Z');
|
|
||||||
+ if (isNaN(d.getTime())) return utcStr;
|
|
||||||
+ return d.toLocaleString('ru-RU', {
|
|
||||||
+ timeZone: 'Asia/Dushanbe',
|
|
||||||
+ day: '2-digit',
|
|
||||||
+ month: '2-digit',
|
|
||||||
+ year: 'numeric',
|
|
||||||
+ hour: '2-digit',
|
|
||||||
+ minute: '2-digit',
|
|
||||||
+ });
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
|
|
||||||
--- a/src/routes/+page.svelte
|
|
||||||
+++ b/src/routes/+page.svelte
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
<script>
|
|
||||||
- import { locale, t, localized } from '$lib/i18n/store.js';
|
|
||||||
+ import { locale, t, localized, formatTs } from '$lib/i18n/store.js';
|
|
||||||
|
|
||||||
export let data;
|
|
||||||
$: lang = $locale;
|
|
||||||
@@ -48,7 +48,7 @@
|
|
||||||
{#each movements as m}
|
|
||||||
<tr>
|
|
||||||
- <td>{m.created_at}</td>
|
|
||||||
+ <td>{formatTs(m.created_at)}</td>
|
|
||||||
<td><span class="pill">{$t('movements.type_' + m.movement_type)}</span></td>
|
|
||||||
<td><a href="/parts/{m.part_id}">{localized(m, 'name', lang)}</a></td>
|
|
||||||
<td class="num">{m.quantity}</td>
|
|
||||||
|
|
||||||
diff --git a/src/routes/admin/reports/+page.svelte b/src/routes/admin/reports/+page.svelte
|
|
||||||
--- a/src/routes/admin/reports/+page.svelte
|
|
||||||
+++ b/src/routes/admin/reports/+page.svelte
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
<script>
|
|
||||||
- import { locale, t, localized, formatMoney } from '$lib/i18n/store.js';
|
|
||||||
+ import { locale, t, localized, formatMoney, formatTs } from '$lib/i18n/store.js';
|
|
||||||
|
|
||||||
export let data;
|
|
||||||
$: lang = $locale;
|
|
||||||
$: ({ sales, topParts, inventory, recentSales } = data);
|
|
||||||
|
|
||||||
- function formatWhen(iso) {
|
|
||||||
- if (!iso) return '';
|
|
||||||
- const d = new Date(iso.replace(' ', 'T') + 'Z');
|
|
||||||
- const pad = (n) => String(n).padStart(2, '0');
|
|
||||||
- return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
||||||
- }
|
|
||||||
</script>
|
|
||||||
@@ -139,7 +132,7 @@
|
|
||||||
{#each recentSales as s}
|
|
||||||
<tr>
|
|
||||||
- <td>{formatWhen(s.saved_at)}</td>
|
|
||||||
+ <td>{formatTs(s.saved_at)}</td>
|
|
||||||
<td class="num">{s.line_count}</td>
|
|
||||||
|
|
||||||
diff --git a/src/routes/invoices/[id]/+page.svelte b/src/routes/invoices/[id]/+page.svelte
|
|
||||||
--- a/src/routes/invoices/[id]/+page.svelte
|
|
||||||
+++ b/src/routes/invoices/[id]/+page.svelte
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
<script>
|
|
||||||
- import { locale, t, localized, formatMoney } from '$lib/i18n/store.js';
|
|
||||||
+ import { locale, t, localized, formatMoney, formatTs } from '$lib/i18n/store.js';
|
|
||||||
|
|
||||||
export let data;
|
|
||||||
$: lang = $locale;
|
|
||||||
@@ -16,7 +16,7 @@
|
|
||||||
<header class="head">
|
|
||||||
<div>
|
|
||||||
<h1>{$t('invoices.saved_title')} #{invoice.id}</h1>
|
|
||||||
- <p class="muted">{invoice.saved_at}</p>
|
|
||||||
+ <p class="muted">{formatTs(invoice.saved_at)}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
diff --git a/src/routes/parts/[id]/+page.svelte b/src/routes/parts/[id]/+page.svelte
|
|
||||||
--- a/src/routes/parts/[id]/+page.svelte
|
|
||||||
+++ b/src/routes/parts/[id]/+page.svelte
|
|
||||||
@@ -1,7 +1,7 @@
|
|
||||||
<script>
|
|
||||||
import { enhance } from '$app/forms';
|
|
||||||
- import { locale, t, localized, formatMoney } from '$lib/i18n/store.js';
|
|
||||||
+ import { locale, t, localized, formatMoney, formatTs } from '$lib/i18n/store.js';
|
|
||||||
|
|
||||||
export let data;
|
|
||||||
export let form;
|
|
||||||
@@ -115,8 +115,8 @@
|
|
||||||
<hr />
|
|
||||||
- <div class="muted small">{$t('common.created')}: {part.created_at}</div>
|
|
||||||
- <div class="muted small">{$t('common.updated')}: {part.updated_at}</div>
|
|
||||||
+ <div class="muted small">{$t('common.created')}: {formatTs(part.created_at)}</div>
|
|
||||||
+ <div class="muted small">{$t('common.updated')}: {formatTs(part.updated_at)}</div>
|
|
||||||
</div>
|
|
||||||
@@ -131,7 +131,7 @@
|
|
||||||
{#each movements as m}
|
|
||||||
<tr>
|
|
||||||
- <td>{m.created_at}</td>
|
|
||||||
+ <td>{formatTs(m.created_at)}</td>
|
|
||||||
<td><span class="pill">{$t('movements.type_' + m.movement_type)}</span></td>
|
|
||||||
Reference in New Issue
Block a user