mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
fix: Allow Date/Luxon objects and additional formats in DateTime validation (#8525)
This commit is contained in:
parent
76cdf75fb9
commit
c419c8592f
|
@ -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
|
||||
|
@ -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 } });
|
||||
};
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
@ -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({
|
||||
|
|
|
@ -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',
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not validate invalid dates', () => {
|
||||
INVALID_DATES.forEach((date) => {
|
||||
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);
|
||||
});
|
||||
|
||||
test.each(INVALID_DATES)('should not validate invalid date "%s"', (date) => {
|
||||
const validationResult = validateFieldType('date', date, 'dateTime');
|
||||
expect(validationResult.valid).toBe(false);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue