Skip to content

Commit

Permalink
fix: Allow Date/Luxon objects and additional formats in DateTime vali…
Browse files Browse the repository at this point in the history
…dation (#8525)
  • Loading branch information
elsmr authored and netroy committed Feb 2, 2024
1 parent 00f5549 commit 98ea7d4
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 17 deletions.
16 changes: 16 additions & 0 deletions packages/workflow/src/TypeValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ export const tryToParseBoolean = (value: unknown): value is boolean => {
};

export const tryToParseDateTime = (value: unknown): DateTime => {
if (value instanceof DateTime && value.isValid) {
return value;
}

if (value instanceof Date) {
const fromJSDate = DateTime.fromJSDate(value);
if (fromJSDate.isValid) {
return fromJSDate;
}
}

const dateString = String(value).trim();

// Rely on luxon to parse different date formats
Expand All @@ -72,6 +83,11 @@ export const tryToParseDateTime = (value: unknown): DateTime => {
return sqlDate;
}

const parsedDateTime = DateTime.fromMillis(Date.parse(dateString));
if (parsedDateTime.isValid) {
return parsedDateTime;
}

throw new ApplicationError('Value is not a valid date', { extra: { dateString } });
};

Expand Down
7 changes: 7 additions & 0 deletions packages/workflow/test/FilterParameter.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { executeFilter } from '@/NodeParameters/FilterParameter';
import type { FilterConditionValue, FilterValue } from '@/Interfaces';
import merge from 'lodash/merge';
import { DateTime } from 'luxon';

type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
Expand Down Expand Up @@ -676,6 +677,12 @@ describe('FilterParameter', () => {
{ left: '2023-11-15T17:10:49.113Z', right: '2023-11-15T17:10:49.113Z', expected: false },
{ left: '2023-11-15T17:10:49.113Z', right: '2023-11-15T17:12:49.113Z', expected: false },
{ left: '2023-11-15T17:10:49.113Z', right: '2023-01-01T00:00:00.000Z', expected: true },
{ left: '2024-01-01', right: new Date('2023-01-01T00:00:00.000Z'), expected: true },
{
left: DateTime.fromFormat('2024-01-01', 'yyyy-MM-dd'),
right: '1-Feb-2024',
expected: false,
},
])('dateTime:after("$left", "$right") === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
Expand Down
38 changes: 21 additions & 17 deletions packages/workflow/test/TypeValidation.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { validateFieldType } from '@/TypeValidation';
import type { DateTime } from 'luxon';
import { DateTime } from 'luxon';

const VALID_ISO_DATES = [
'1994-11-05T08:15:30-05:00',
Expand Down Expand Up @@ -30,12 +30,18 @@ const VALID_RFC_DATES = [

const VALID_SQL_DATES = ['2008-11-11', '2008-11-11 13:23:44'];

const OTHER_VALID_DATES = [
'Wed, 17 May 2023 10:52:32',
'SMT, 17 May 2023 10:52:32',
'1-Feb-2024',
new Date(),
DateTime.now(),
];

const INVALID_DATES = [
'1994-11-05M08:15:30-05:00',
'18-05-2020',
'',
'Wed, 17 May 2023 10:52:32',
'SMT, 17 May 2023 10:52:32',
'1685084980', // We are not supporting timestamps
'1685085012135',
1685084980,
Expand All @@ -45,40 +51,38 @@ const INVALID_DATES = [
];

describe('Type Validation', () => {
it('should validate and cast ISO dates', () => {
VALID_ISO_DATES.forEach((date) => {
describe('Dates', () => {
test.each(VALID_ISO_DATES)('should validate and cast ISO date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
});
});

it('should validate and cast RFC 2822 dates', () => {
VALID_RFC_DATES.forEach((date) => {
test.each(VALID_RFC_DATES)('should validate and cast RFC2822 date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
});
});

it('should validate and cast HTTP dates', () => {
VALID_HTTP_DATES.forEach((date) => {
test.each(VALID_HTTP_DATES)('should validate and cast HTTP date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
});
});

it('should validate and cast SQL dates', () => {
VALID_SQL_DATES.forEach((date) => {
test.each(VALID_SQL_DATES)('should validate and cast SQL date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
});

test.each(OTHER_VALID_DATES)('should validate and cast date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
});
});

it('should not validate invalid dates', () => {
INVALID_DATES.forEach((date) => {
test.each(INVALID_DATES)('should not validate invalid date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(false);
});
Expand Down

0 comments on commit 98ea7d4

Please sign in to comment.