fix: SQLite timestamp timezone ambiguity — convert to proper UTC ISO strings
This commit is contained in:
parent
df9d6fbf6d
commit
3a19303d4d
|
|
@ -18,6 +18,20 @@ function errorMessage(err) {
|
||||||
return err?.message || String(err);
|
return err?.message || String(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SQLite stores datetime('now') as "YYYY-MM-DD HH:MM:SS" (UTC, no Z).
|
||||||
|
// Without the Z suffix, JS Date parses it as LOCAL time, creating timezone
|
||||||
|
// inconsistencies when mixed with ISO strings that do have Z.
|
||||||
|
// This ensures all timestamps sent to clients are unambiguous UTC ISO strings.
|
||||||
|
function toIso(sqliteOrIso) {
|
||||||
|
if (!sqliteOrIso) return null;
|
||||||
|
const s = String(sqliteOrIso).trim();
|
||||||
|
// Already ISO with Z or offset — return as-is
|
||||||
|
if (s.includes('T') && (s.endsWith('Z') || s.match(/[+-]\d{2}:\d{2}$/))) return s;
|
||||||
|
// SQLite format "YYYY-MM-DD HH:MM:SS" — append Z to declare it UTC
|
||||||
|
if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}/.test(s)) return s.replace(' ', 'T') + 'Z';
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
function monthRange(now) {
|
function monthRange(now) {
|
||||||
const year = now.getFullYear();
|
const year = now.getFullYear();
|
||||||
const month = now.getMonth() + 1;
|
const month = now.getMonth() + 1;
|
||||||
|
|
@ -291,7 +305,7 @@ router.get('/', async (req, res) => {
|
||||||
source_count: sourceRow.source_count ?? 0,
|
source_count: sourceRow.source_count ?? 0,
|
||||||
account_count: accountRow.account_count ?? 0,
|
account_count: accountRow.account_count ?? 0,
|
||||||
transaction_count: txRow.transaction_count ?? 0,
|
transaction_count: txRow.transaction_count ?? 0,
|
||||||
last_sync_at: sourceRow.last_sync_at || null,
|
last_sync_at: toIso(sourceRow.last_sync_at),
|
||||||
last_error: errorRow?.last_error || null,
|
last_error: errorRow?.last_error || null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +319,7 @@ router.get('/', async (req, res) => {
|
||||||
const raw = getSetting('cleanup_last_result');
|
const raw = getSetting('cleanup_last_result');
|
||||||
cleanup = {
|
cleanup = {
|
||||||
ok: true,
|
ok: true,
|
||||||
last_run_at: getSetting('cleanup_last_run_at') || null,
|
last_run_at: toIso(getSetting('cleanup_last_run_at')),
|
||||||
last_result: raw ? JSON.parse(raw) : null,
|
last_result: raw ? JSON.parse(raw) : null,
|
||||||
};
|
};
|
||||||
} catch { /* non-fatal */ }
|
} catch { /* non-fatal */ }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue