diff --git a/src/date_utils.ts b/src/date_utils.ts index c8f49746e..2d28949e1 100644 --- a/src/date_utils.ts +++ b/src/date_utils.ts @@ -318,6 +318,20 @@ export function parseDate( return parsedDate; } } + + // When strictParsing is false, try native Date parsing as a fallback + // This allows flexible input formats like "12/05/2025" or "2025-12-16" + // even when the dateFormat prop specifies a different format. + // Only attempt this for inputs that look like complete dates (minimum + // length of 8 characters, e.g., "1/1/2000") to avoid parsing partial + // inputs like "03/" or "2000" which should be handled by parseDateForNavigation. + if (!strictParsing && value && value.length >= 8) { + const nativeDate = new Date(value); + if (isValidDate(nativeDate)) { + return nativeDate; + } + } + return null; } diff --git a/src/test/date_utils_test.test.ts b/src/test/date_utils_test.test.ts index 961e69559..ee5b98047 100644 --- a/src/test/date_utils_test.test.ts +++ b/src/test/date_utils_test.test.ts @@ -1094,7 +1094,10 @@ describe("date_utils", () => { expect(parseDate(valueEn, dateFormat, undefined, false)).toEqual( expected, ); - expect(parseDate(valueEn, dateFormat, locale, false)).toBeNull(); + // With native Date fallback (restored in v8.x), English month names + // are parsed even when a different locale is specified, because + // the native Date constructor is locale-agnostic + expect(parseDate(valueEn, dateFormat, locale, false)).toEqual(expected); }); it("should not parse date based on locale without a given locale", () => { @@ -1117,6 +1120,63 @@ describe("date_utils", () => { expect(actual).toEqual(expected); }); + + describe("native Date fallback when strictParsing is false (#6164)", () => { + it("should parse date in different format using native Date fallback", () => { + // User types MM/dd/yyyy but dateFormat is yyyy-MM-dd + const value = "12/05/2025"; + const dateFormat = "yyyy-MM-dd"; + + const result = parseDate(value, dateFormat, undefined, false); + expect(result).not.toBeNull(); + expect(result?.getFullYear()).toBe(2025); + expect(result?.getMonth()).toBe(11); // December (0-indexed) + expect(result?.getDate()).toBe(5); + }); + + it("should parse ISO date string using native Date fallback", () => { + const value = "2025-12-16"; + const dateFormat = "MM/dd/yyyy"; + + const result = parseDate(value, dateFormat, undefined, false); + expect(result).not.toBeNull(); + expect(result?.getFullYear()).toBe(2025); + expect(result?.getMonth()).toBe(11); // December + expect(result?.getDate()).toBe(16); + }); + + it("should parse date with time using native Date fallback", () => { + const value = "2025-12-16 3:31:01 PM"; + const dateFormat = "yyyy-MM-dd hh:mm aa"; + + const result = parseDate(value, dateFormat, undefined, false); + expect(result).not.toBeNull(); + expect(result?.getFullYear()).toBe(2025); + expect(result?.getMonth()).toBe(11); // December + expect(result?.getDate()).toBe(16); + expect(result?.getHours()).toBe(15); // 3 PM = 15:00 + expect(result?.getMinutes()).toBe(31); + }); + + it("should NOT use native Date fallback when strictParsing is true", () => { + const value = "12/05/2025"; + const dateFormat = "yyyy-MM-dd"; + + const result = parseDate(value, dateFormat, undefined, true); + expect(result).toBeNull(); + }); + + it("should prefer exact format match over native Date fallback", () => { + const value = "2025-12-05"; + const dateFormat = "yyyy-MM-dd"; + + const result = parseDate(value, dateFormat, undefined, false); + expect(result).not.toBeNull(); + expect(result?.getFullYear()).toBe(2025); + expect(result?.getMonth()).toBe(11); // December + expect(result?.getDate()).toBe(5); + }); + }); }); describe("isMonthInRange", () => {