diff --git a/apps/web/src/common/utils/time.test.ts b/apps/web/src/common/utils/time.test.ts index 8479d4647..ce104d10b 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 fce7917ae..5efe299e9 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] }); };