diff --git a/spiffworkflow-frontend/src/config.tsx b/spiffworkflow-frontend/src/config.tsx index 0833d055..02fca38f 100644 --- a/spiffworkflow-frontend/src/config.tsx +++ b/spiffworkflow-frontend/src/config.tsx @@ -80,6 +80,7 @@ const PROCESS_STATUSES = [ // with time: yyyy-MM-dd HH:mm:ss let generalDateFormat = 'yyyy-MM-dd'; +// let generalDateFormat = 'dd-MMM-yyyy'; if ( 'spiffworkflowFrontendJsenv' in window && 'DATE_FORMAT' in window.spiffworkflowFrontendJsenv diff --git a/spiffworkflow-frontend/src/services/DateAndTimeService.test.tsx b/spiffworkflow-frontend/src/services/DateAndTimeService.test.tsx index 1264b096..137ec329 100644 --- a/spiffworkflow-frontend/src/services/DateAndTimeService.test.tsx +++ b/spiffworkflow-frontend/src/services/DateAndTimeService.test.tsx @@ -1,5 +1,42 @@ import DateAndTimeService from './DateAndTimeService'; +test('it can tell if a string looks like a date', () => { + const validDates = [ + '2024-06-01', + '14-06-2024', + '1-06-2024', + '14-6-2024', + '14-Jun-2024', + '14-March-2024', + 'March 4, 2024', + '4 March 2024', + '04/03/2024', + '04.03.2024', + ]; + validDates.forEach((dateString: string) => { + try { + expect(DateAndTimeService.stringLooksLikeADate(dateString)).toBe(true); + } catch (exception) { + throw Error(`Date failed: ${dateString}: ${exception}`); + } + }); + + const invalidDates = [ + '2024-06-0', + '2024-6-01', + '14-06-202', + '14-Jun-202', + '14#06#20204', + ]; + invalidDates.forEach((dateString: string) => { + try { + expect(DateAndTimeService.stringLooksLikeADate(dateString)).toBe(false); + } catch (exception) { + throw Error(`Date failed: ${dateString}: ${exception}`); + } + }); +}); + test('it can keep the correct date when converting seconds to date', () => { const dateString = DateAndTimeService.convertSecondsToFormattedDateString(1666325400); @@ -25,6 +62,7 @@ test('it can properly format a duration', () => { test('it can get the correct date format from string', () => { const expectedDateString = '2024-03-04'; const newDateFormat = 'dd-MMM-yyyy'; + const marchDate = 'March 4, 2024'; expect( DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat( @@ -38,7 +76,7 @@ test('it can get the correct date format from string', () => { ).toEqual(expectedDateString); expect( DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat( - 'March 4, 2024', + marchDate, ), ).toEqual(expectedDateString); expect( @@ -65,7 +103,7 @@ test('it can get the correct date format from string', () => { ).toEqual(expectedDateString); expect( DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat( - 'March 4, 2024', + marchDate, newDateFormat, ), ).toEqual(expectedDateString); diff --git a/spiffworkflow-frontend/src/services/DateAndTimeService.tsx b/spiffworkflow-frontend/src/services/DateAndTimeService.tsx index d8bc418b..1c06a07e 100644 --- a/spiffworkflow-frontend/src/services/DateAndTimeService.tsx +++ b/spiffworkflow-frontend/src/services/DateAndTimeService.tsx @@ -14,6 +14,18 @@ const FOUR_HOURS_IN_SECONDS = SECONDS_IN_HOUR * 4; const REFRESH_INTERVAL_SECONDS = 5; const REFRESH_TIMEOUT_SECONDS = FOUR_HOURS_IN_SECONDS; +const stringLooksLikeADate = (dateString: string): boolean => { + // We had been useing date-fns parse to really check if a date is valid however it attempts to parse dates like 14-06-2 because it thinks it is 14-06-0002. + // This results in a validate date but has a negative time with getTime which is a valid number however we do not want dates like this at all. + // Checking for negative numbers seem wrong so use a regex to see if it looks anything like a date. + return ( + (dateString.match(/^\d{4}[-/.]\d{2}[-/.]\d{2}$/) || + dateString.match(/^(\d{1,2}|\w+)[-/.](\d{1,2}|\w+)[-/.]\d{4}$/) || + dateString.match(/^\w+ +\d+, +\d{4}$/) || + dateString.match(/^\d+ +\w+ +\d{4}$/)) !== null + ); +}; + const convertDateToSeconds = (date: any, onChangeFunction: any = null) => { let dateInSeconds = date; if (date !== null) { @@ -44,7 +56,11 @@ const dateStringToYMDFormat = (dateString: string) => { if (dateString === undefined || dateString === null) { return dateString; } - if (dateString && dateString.match(/^\d{4}-\d{2}-\d{2}$/)) { + + if ( + dateString.match(/^\d{4}-\d{2}-\d{2}$/) || + !stringLooksLikeADate(dateString) + ) { return dateString; } const newDate = parse(dateString, DATE_FORMAT, new Date()); @@ -160,7 +176,7 @@ const attemptToConvertUnknownDateStringFormatToKnownFormat = ( } let newDateString = dateString; // if the date starts with 4 digits then assume in y-m-d format and avoid all of this - if (dateString.length >= 10 && !dateString.match(/^\d{4}/)) { + if (stringLooksLikeADate(dateString) && !dateString.match(/^\d{4}/)) { // if the date format should contain month names or abbreviations but does not have letters // then attempt to parse in the same format but with digit months instead of letters @@ -252,6 +268,7 @@ const DateAndTimeService = { formatDateTime, formatDurationForDisplay, secondsToDuration, + stringLooksLikeADate, ymdDateStringToConfiguredFormat, };