Date format fixer (#1319)

* attmept to figure out what date format the user is inputting w/ burnettk

* reverted default date config w/ burnettk

* added tests for the new date formatter function

* fixed outdated comment

---------

Co-authored-by: jasquat <jasquat@users.noreply.github.com>
This commit is contained in:
jasquat 2024-04-01 20:39:29 +00:00 committed by GitHub
parent cef93033e8
commit b507f45fb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 135 additions and 3 deletions

View File

@ -6,10 +6,15 @@ import {
StrictRJSFSchema,
WidgetProps,
} from '@rjsf/utils';
import { parse } from 'date-fns';
import { useCallback } from 'react';
import { useDebouncedCallback } from 'use-debounce';
import { DATE_FORMAT_CARBON, DATE_FORMAT_FOR_DISPLAY } from '../../../config';
import {
DATE_FORMAT,
DATE_FORMAT_CARBON,
DATE_FORMAT_FOR_DISPLAY,
} from '../../../config';
import DateAndTimeService from '../../../services/DateAndTimeService';
import { getCommonAttributes } from '../../helpers';
@ -73,8 +78,12 @@ export default function BaseInputTemplate<
);
const addDebouncedOnChangeDate = useDebouncedCallback(
(target: React.ChangeEvent<HTMLInputElement>) => {
_onChange(target);
(fullObject: React.ChangeEvent<HTMLInputElement>) => {
fullObject.target.value =
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
fullObject.target.value
);
_onChange(fullObject);
},
// delay in ms
1000
@ -93,6 +102,8 @@ export default function BaseInputTemplate<
// it should in be y-m-d when it gets here.
let dateValue: string | null = value;
if (value || value === 0) {
// it would be good if we could compare against the length of the desired format but that doesn't work in all cases and causes some issues.
// 10 seems to be a good value check against.
if (value.length < 10) {
dateValue = value;
} else {

View File

@ -5,6 +5,7 @@ test('it can keep the correct date when converting seconds to date', () => {
DateAndTimeService.convertSecondsToFormattedDateString(1666325400);
expect(dateString).toEqual('2022-10-21');
});
test('it can properly format a duration', () => {
expect(DateAndTimeService.formatDurationForDisplay('0')).toEqual('0s');
expect(DateAndTimeService.formatDurationForDisplay('60')).toEqual('1m');
@ -20,3 +21,82 @@ test('it can properly format a duration', () => {
'365d 12m 45s'
);
});
test('it can get the correct date format from string', () => {
const expectedDateString = '2024-03-04';
const newDateFormat = 'dd-MMM-yyyy';
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
expectedDateString
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'03-04-2024'
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'March 4, 2024'
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'mar-4-2024'
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'03/04/2024'
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'03.04.2024'
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'04-03-2024',
newDateFormat
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'March 4, 2024',
newDateFormat
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'4-mar-2024',
newDateFormat
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'4 March 2024',
newDateFormat
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'04/03/2024',
newDateFormat
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
'04.03.2024',
newDateFormat
)
).toEqual(expectedDateString);
expect(
DateAndTimeService.attemptToConvertUnknownDateStringFormatToKnownFormat(
expectedDateString,
newDateFormat
)
).toEqual(expectedDateString);
});

View File

@ -147,6 +147,46 @@ const secondsToDuration = (secNum: number) => {
return duration;
};
const attemptToConvertUnknownDateStringFormatToKnownFormat = (
dateString: string,
targetDateFormat?: string
) => {
let dateFormat = targetDateFormat;
if (!dateFormat) {
dateFormat = DATE_FORMAT;
}
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 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
if (!dateString.match(/[a-zA-Z]+/) && dateFormat.match(/MMM/)) {
const numericalDateFormat = dateFormat.replaceAll(/MMM*/g, 'MM');
const dateFormatRegex = new RegExp(
numericalDateFormat
.replace('dd', '\\d{2}')
.replace('MM', '\\d{2}')
.replace('yyyy', '\\d{4}')
);
const normalizedDateString = dateString.replaceAll(/[.-/]+/g, '-');
if (normalizedDateString.match(dateFormatRegex)) {
const newDate = parse(
normalizedDateString,
dateFormat.replaceAll(/MMM*/g, 'MM'),
new Date()
);
newDateString = convertDateObjectToFormattedString(newDate) || '';
}
} else {
// NOTE: do not run Date.parse with y-m-d formats since it returns dates in a different timezone from other formats
const newDate = new Date(Date.parse(`${dateString}`));
newDateString = convertDateObjectToFormattedString(newDate) || '';
}
}
return newDateString;
};
const formatDurationForDisplay = (value: any) => {
if (value === undefined) {
return undefined;
@ -193,6 +233,7 @@ const DateAndTimeService = {
REFRESH_INTERVAL_SECONDS,
REFRESH_TIMEOUT_SECONDS,
attemptToConvertUnknownDateStringFormatToKnownFormat,
convertDateAndTimeStringsToDate,
convertDateAndTimeStringsToSeconds,
convertDateObjectToFormattedHoursMinutes,