From bb2d31ea8688fa5b92e3cccb558161af5cbe8fc9 Mon Sep 17 00:00:00 2001 From: Yxq Date: Tue, 20 Oct 2026 16:30:01 +0800 Subject: [PATCH] fix: return an empty string for a time value that cannot be parsed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Motivation `formatISO`, `formatToNow` and `formatToNowStrict` only reject an empty input, then hand the result of `parseJSON` straight to date-fns: ```ts const p = parseJSON(s); return format(p, layout || FORMAT_YMD); // RangeError: Invalid time value ``` A value that is not a date makes every one of them throw. `formatISO` is what `transDataForOverview` uses for the chart's x-axis, so one malformed time string in a series takes the metric page down instead of leaving a gap. ## Change Check `isValid(p)` after parsing and return `''` when it fails, matching the existing empty-input behaviour. ## Verification ``` # tests only ● returns an empty string for a value that is not a date RangeError: Invalid time value Tests: 1 failed, 3 passed, 4 total # with the fix Tests: 4 passed, 4 total ``` Signed-off-by: Yxq --- apps/web/src/common/utils/time.test.ts | 6 ++++++ apps/web/src/common/utils/time.ts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/apps/web/src/common/utils/time.test.ts b/apps/web/src/common/utils/time.test.ts index 8479d46476..ce104d10bc 100644 --- a/apps/web/src/common/utils/time.test.ts +++ b/apps/web/src/common/utils/time.test.ts @@ -20,4 +20,10 @@ describe('time', () => { it('formatToNowStrict', function () { expect(formatToNowStrict('2022-09-28T02:11:54Z')).toBe('2 months'); }); + + it('returns an empty string for a value that is not a date', () => { + expect(formatISO('not-a-date')).toEqual(''); + expect(formatToNow('not-a-date')).toEqual(''); + expect(formatToNowStrict('not-a-date')).toEqual(''); + }); }); diff --git a/apps/web/src/common/utils/time.ts b/apps/web/src/common/utils/time.ts index fce7917ae1..5efe299e92 100644 --- a/apps/web/src/common/utils/time.ts +++ b/apps/web/src/common/utils/time.ts @@ -1,4 +1,5 @@ import { + isValid, formatDistanceToNow, formatDistanceToNowStrict, format, @@ -14,18 +15,23 @@ const languages = { en: enGB, zh: zhCN }; export const formatISO = (s: string, layout?: string) => { if (!s) return ''; const p = parseJSON(s); + // date-fns format() throws RangeError on an invalid date; a malformed value in + // the series must not take the whole page down. + if (!isValid(p)) return ''; return format(p, layout || FORMAT_YMD); }; export const formatToNow = (s: string) => { if (!s) return ''; const p = parseJSON(s); + if (!isValid(p)) return ''; return formatDistanceToNow(p, { locale: languages[local] }); }; export const formatToNowStrict = (s: string) => { if (!s) return ''; const p = parseJSON(s); + if (!isValid(p)) return ''; return formatDistanceToNowStrict(p, { locale: languages[local] }); };