From 23a96d3ea7a034e957378d88956627cb96e2d76c Mon Sep 17 00:00:00 2001 From: Brad Groux Date: Thu, 5 Feb 2026 19:24:22 -0600 Subject: [PATCH] feat: add timezone offset to all API response meta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every API response now includes: meta.timezone: 'UTC-06:00' (human-readable) meta.utcOffset: -6 (numeric, for client-side math) Uses system time — no config needed. --- server/src/middleware/response-envelope.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/server/src/middleware/response-envelope.ts b/server/src/middleware/response-envelope.ts index 1ba42ffc..268c6d86 100644 --- a/server/src/middleware/response-envelope.ts +++ b/server/src/middleware/response-envelope.ts @@ -36,6 +36,8 @@ export interface PaginationMeta { interface EnvelopeMeta { timestamp: string; + timezone: string; + utcOffset: number; requestId?: string; pagination?: PaginationMeta; } @@ -108,8 +110,17 @@ export function responseEnvelopeMiddleware(_req: Request, res: Response, next: N // Override res.json res.json = function envelopedJson(data?: unknown): Response { + const now = new Date(); + const offsetMinutes = now.getTimezoneOffset(); // positive = west of UTC + const offsetHours = -offsetMinutes / 60; // flip sign: CST = -6 + const sign = offsetHours >= 0 ? '+' : '-'; + const absH = String(Math.floor(Math.abs(offsetHours))).padStart(2, '0'); + const absM = String(Math.abs(offsetMinutes) % 60).padStart(2, '0'); + const meta: EnvelopeMeta = { - timestamp: new Date().toISOString(), + timestamp: now.toISOString(), + timezone: `UTC${sign}${absH}:${absM}`, + utcOffset: offsetHours, }; // Include requestId if available (set by request-id middleware)