From 2fefdaf36ab65a2a82b96deb76999aef7b04cccf Mon Sep 17 00:00:00 2001 From: BOHA Date: Tue, 24 Mar 2026 07:45:29 +0100 Subject: [PATCH] fix: serialize dates as local time in JSON responses, not UTC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prisma reads MySQL DATETIME as UTC Date objects. JSON.stringify calls Date.toJSON() which defaults to toISOString() — outputting UTC with Z suffix. Frontend then shows times shifted by -1 hour. Override Date.toJSON to format using local getters (getHours etc.) instead of getUTCHours. Combined with TZ=Europe/Prague, all API responses now contain Czech local times without Z suffix. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/config/env.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/config/env.ts b/src/config/env.ts index 402f6b7..55312be 100644 --- a/src/config/env.ts +++ b/src/config/env.ts @@ -4,6 +4,20 @@ dotenv.config(); // Set timezone for Date operations — all attendance/time records are in Czech local time process.env.TZ = process.env.TZ || 'Europe/Prague'; +// Override Date.toJSON to serialize as local time instead of UTC +// MySQL DATETIME stores local time, Prisma creates Date objects, +// JSON.stringify calls toJSON() which defaults to toISOString() (UTC with Z suffix). +// This causes times to shift by timezone offset on the frontend. +Date.prototype.toJSON = function () { + const y = this.getFullYear(); + const m = String(this.getMonth() + 1).padStart(2, '0'); + const d = String(this.getDate()).padStart(2, '0'); + const h = String(this.getHours()).padStart(2, '0'); + const min = String(this.getMinutes()).padStart(2, '0'); + const s = String(this.getSeconds()).padStart(2, '0'); + return `${y}-${m}-${d}T${h}:${min}:${s}`; +}; + function required(key: string): string { const val = process.env[key]; if (!val) throw new Error(`Missing required env variable: ${key}`);