mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-11-13 22:05:15 +00:00
Fixes #4844 with more defensive date parsing
All checks were successful
Close stale issues and PRs / stale (push) Successful in 23s
All checks were successful
Close stale issues and PRs / stale (push) Successful in 23s
This commit is contained in:
74
frontend/src/locale/Utils.test.tsx
Normal file
74
frontend/src/locale/Utils.test.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { formatDateTime } from "src/locale";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
|
||||
describe("DateFormatter", () => {
|
||||
// Keep a reference to the real Intl to restore later
|
||||
const RealIntl = global.Intl;
|
||||
const desiredTimeZone = "Europe/London";
|
||||
const desiredLocale = "en-GB";
|
||||
|
||||
beforeAll(() => {
|
||||
// Ensure Node-based libs using TZ behave deterministically
|
||||
try {
|
||||
process.env.TZ = desiredTimeZone;
|
||||
} catch {
|
||||
// ignore if not available
|
||||
}
|
||||
|
||||
// Mock Intl.DateTimeFormat so formatting is stable regardless of host
|
||||
const MockedDateTimeFormat = class extends RealIntl.DateTimeFormat {
|
||||
constructor(_locales?: string | string[], options?: Intl.DateTimeFormatOptions) {
|
||||
super(desiredLocale, {
|
||||
...options,
|
||||
timeZone: desiredTimeZone,
|
||||
});
|
||||
}
|
||||
} as unknown as typeof Intl.DateTimeFormat;
|
||||
|
||||
global.Intl = {
|
||||
...RealIntl,
|
||||
DateTimeFormat: MockedDateTimeFormat,
|
||||
};
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
// Restore original Intl after tests
|
||||
global.Intl = RealIntl;
|
||||
});
|
||||
|
||||
it("format date from iso date", () => {
|
||||
const value = "2024-01-01T00:00:00.000Z";
|
||||
const text = formatDateTime(value);
|
||||
expect(text).toBe("Monday, 01/01/2024, 12:00:00 am");
|
||||
});
|
||||
|
||||
it("format date from unix timestamp number", () => {
|
||||
const value = 1762476112;
|
||||
const text = formatDateTime(value);
|
||||
expect(text).toBe("Friday, 07/11/2025, 12:41:52 am");
|
||||
});
|
||||
|
||||
it("format date from unix timestamp string", () => {
|
||||
const value = "1762476112";
|
||||
const text = formatDateTime(value);
|
||||
expect(text).toBe("Friday, 07/11/2025, 12:41:52 am");
|
||||
});
|
||||
|
||||
it("catch bad format from string", () => {
|
||||
const value = "this is not a good date";
|
||||
const text = formatDateTime(value);
|
||||
expect(text).toBe("this is not a good date");
|
||||
});
|
||||
|
||||
it("catch bad format from number", () => {
|
||||
const value = -100;
|
||||
const text = formatDateTime(value);
|
||||
expect(text).toBe("-100");
|
||||
});
|
||||
|
||||
it("catch bad format from number as string", () => {
|
||||
const value = "-100";
|
||||
const text = formatDateTime(value);
|
||||
expect(text).toBe("-100");
|
||||
});
|
||||
});
|
||||
@@ -11,13 +11,19 @@ const isUnixTimestamp = (value: unknown): boolean => {
|
||||
return false;
|
||||
};
|
||||
|
||||
const DateTimeFormat = (value: string | number): string => {
|
||||
if (typeof value !== "number" && typeof value !== "string") return `${value}`;
|
||||
|
||||
const parseDate = (value: string | number): Date | null => {
|
||||
if (typeof value !== "number" && typeof value !== "string") return null;
|
||||
try {
|
||||
return isUnixTimestamp(value) ? fromUnixTime(+value) : parseISO(`${value}`);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const formatDateTime = (value: string | number): string => {
|
||||
const d = parseDate(value);
|
||||
if (!d) return `${value}`;
|
||||
try {
|
||||
const d = isUnixTimestamp(value)
|
||||
? fromUnixTime(+value)
|
||||
: parseISO(`${value}`);
|
||||
return intlFormat(d, {
|
||||
weekday: "long",
|
||||
year: "numeric",
|
||||
@@ -33,4 +39,4 @@ const DateTimeFormat = (value: string | number): string => {
|
||||
}
|
||||
};
|
||||
|
||||
export { DateTimeFormat };
|
||||
export { formatDateTime, parseDate, isUnixTimestamp };
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from "./DateTimeFormat";
|
||||
export * from "./IntlProvider";
|
||||
export * from "./Utils";
|
||||
|
||||
Reference in New Issue
Block a user