diff --git a/mathesar_ui/src/utils/date-time/DateTimeFormatter.ts b/mathesar_ui/src/utils/date-time/DateTimeFormatter.ts index 82ed06d344..14450f5051 100644 --- a/mathesar_ui/src/utils/date-time/DateTimeFormatter.ts +++ b/mathesar_ui/src/utils/date-time/DateTimeFormatter.ts @@ -41,6 +41,33 @@ function parseKeywords(input: string): Dayjs | undefined { } } +function makeLooseVariants(formats: string[]): string[] { + const variants = new Set(); + + for (const f of formats) { + variants.add(f); + + if (f.includes('HH')) { + variants.add(f.replace(/HH/g, 'H')); + } + + if (f.includes(':ss')) { + variants.add(f.replace(':ss', '')); + variants.add(f.replace(':ss.Z', '')); + variants.add(f.replace(':ss Z', '')); + variants.add(f.replace(':ssZZ', '')); + } + + if (f.includes('T')) { + variants.add(f.replace('T', ' ')); + } else if (f.includes(' ')) { + variants.add(f.replace(' ', 'T')); + } + } + + return Array.from(variants); +} + function parseWithSpec( input: string, spec: DateTimeSpecification, @@ -52,7 +79,9 @@ function parseWithSpec( ...canonicalFormats, ]; - const strictResult = dayjs(input, allFormats, true); + const looseFormats = makeLooseVariants(allFormats); + + const strictResult = dayjs(input, looseFormats, true); if (strictResult.isValid()) return strictResult; const canonicalResult = dayjs(input, canonicalFormats); @@ -72,9 +101,16 @@ export default class DateTimeFormatter implements InputFormatter { * @param input could come from the user or from an API response */ parse(input: string): ParseResult { - const dayjsValue = + let dayjsValue = parseKeywords(input) ?? parseWithSpec(input, this.specification); + if (!dayjsValue) { + const permissive = dayjs(input); + if (permissive.isValid()) { + dayjsValue = permissive; + } + } + const value = (() => { if (dayjsValue) { // If we were able to parse the input, then we return the canonical diff --git a/mathesar_ui/src/utils/date-time/DateTimeSpecification.ts b/mathesar_ui/src/utils/date-time/DateTimeSpecification.ts index acab8b5cc7..b59433314f 100644 --- a/mathesar_ui/src/utils/date-time/DateTimeSpecification.ts +++ b/mathesar_ui/src/utils/date-time/DateTimeSpecification.ts @@ -74,9 +74,12 @@ const timeFormattingStringMap: Record = { const commonTimeFormattingStrings = [ 'hh:mm:ss a', 'HH:mm:ss', + 'H:mm:ss', 'hh:mm a', 'HH:mm', + 'H:mm', ]; + const commonTimeWithTZFormattingStrings = [ ...commonTimeFormattingStrings, ...combine( @@ -139,7 +142,7 @@ export default class DateTimeSpecification { if (this.type === 'timestamp') { return combine( allDateFormattingStrings, - commonTimeFormattingStrings, + ['HH:mm:ss', 'H:mm:ss', 'HH:mm', 'H:mm', 'hh:mm:ss a', 'hh:mm a'], (a, b) => `${a} ${b}`, ); }