From 91dfd5c2394c70c12fbb08cc5a6684098e70afb9 Mon Sep 17 00:00:00 2001 From: Akash Santra Date: Mon, 27 Apr 2026 02:21:28 +0530 Subject: [PATCH 1/3] fix: incorrect 24h time detection for non-AM/PM locales --- packages/lib/timeFormat.test.ts | 40 +++++++++++++++++++++++++++++++++ packages/lib/timeFormat.ts | 16 ++++++------- 2 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 packages/lib/timeFormat.test.ts diff --git a/packages/lib/timeFormat.test.ts b/packages/lib/timeFormat.test.ts new file mode 100644 index 00000000000000..4a81d6d8194625 --- /dev/null +++ b/packages/lib/timeFormat.test.ts @@ -0,0 +1,40 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; + +vi.mock("@calcom/lib/webstorage", () => ({ + localStorage: { + getItem: vi.fn().mockReturnValue(null), + setItem: vi.fn(), + }, +})); + +import { isBrowserLocale24h } from "./timeFormat"; + +describe("isBrowserLocale24h", () => { + beforeEach(() => { + vi.restoreAllMocks(); + }); + + it("returns true for 24h hourCycle", () => { + vi.spyOn(Intl, "DateTimeFormat").mockImplementation( + function () { + return { + resolvedOptions: () => ({ hourCycle: "h23" }), + } as any; + } as any + ); + + expect(isBrowserLocale24h()).toBe(true); + }); + + it("returns false for 12h hourCycle", () => { + vi.spyOn(Intl, "DateTimeFormat").mockImplementation( + function () { + return { + resolvedOptions: () => ({ hourCycle: "h12" }), + } as any; + } as any + ); + + expect(isBrowserLocale24h()).toBe(false); + }); +}); \ No newline at end of file diff --git a/packages/lib/timeFormat.ts b/packages/lib/timeFormat.ts index 4864df4119b7bb..9998a8d17045e3 100644 --- a/packages/lib/timeFormat.ts +++ b/packages/lib/timeFormat.ts @@ -41,14 +41,14 @@ export const isBrowserLocale24h = () => { } else if (localStorageTimeFormat === false) { return false; } - // Intl.DateTimeFormat with value=undefined uses local browser settings. - if (!!new Intl.DateTimeFormat(undefined, { hour: "numeric" }).format(0).match(/M/i)) { - setIs24hClockInLocalStorage(false); - return false; - } else { - setIs24hClockInLocalStorage(true); - return true; - } + + const formatter = new Intl.DateTimeFormat(undefined, { hour: "numeric" }); + const hourCycle = (formatter.resolvedOptions() as any).hourCycle; + + const is24h = hourCycle === "h23" || hourCycle === "h24"; + + setIs24hClockInLocalStorage(is24h); + return is24h; }; /** From b8d9bf9f67d64ff578b1e7b386f924750a186cb1 Mon Sep 17 00:00:00 2001 From: Akash Santra Date: Mon, 27 Apr 2026 02:32:57 +0530 Subject: [PATCH 2/3] chore: improve test typing for Intl.DateTimeFormat mock --- packages/lib/timeFormat.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/lib/timeFormat.test.ts b/packages/lib/timeFormat.test.ts index 4a81d6d8194625..6e1a4f77e52670 100644 --- a/packages/lib/timeFormat.test.ts +++ b/packages/lib/timeFormat.test.ts @@ -16,11 +16,11 @@ describe("isBrowserLocale24h", () => { it("returns true for 24h hourCycle", () => { vi.spyOn(Intl, "DateTimeFormat").mockImplementation( - function () { + function (): Intl.DateTimeFormat { return { resolvedOptions: () => ({ hourCycle: "h23" }), - } as any; - } as any + } as unknown as Intl.DateTimeFormat; + } ); expect(isBrowserLocale24h()).toBe(true); @@ -28,11 +28,11 @@ describe("isBrowserLocale24h", () => { it("returns false for 12h hourCycle", () => { vi.spyOn(Intl, "DateTimeFormat").mockImplementation( - function () { + function (): Intl.DateTimeFormat { return { resolvedOptions: () => ({ hourCycle: "h12" }), - } as any; - } as any + } as unknown as Intl.DateTimeFormat; + } ); expect(isBrowserLocale24h()).toBe(false); From 634524dffb2f5b978539e30386e6c1480c5bc311 Mon Sep 17 00:00:00 2001 From: Akash Santra Date: Mon, 27 Apr 2026 02:38:43 +0530 Subject: [PATCH 3/3] chore: replace any cast with narrower type for hourCycle --- packages/lib/timeFormat.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lib/timeFormat.ts b/packages/lib/timeFormat.ts index 9998a8d17045e3..a3fb70569abcf5 100644 --- a/packages/lib/timeFormat.ts +++ b/packages/lib/timeFormat.ts @@ -43,7 +43,7 @@ export const isBrowserLocale24h = () => { } const formatter = new Intl.DateTimeFormat(undefined, { hour: "numeric" }); - const hourCycle = (formatter.resolvedOptions() as any).hourCycle; + const hourCycle = (formatter.resolvedOptions() as { hourCycle?: string }).hourCycle; const is24h = hourCycle === "h23" || hourCycle === "h24";