Skip to content

Commit

Permalink
fix: filtering on dateOnly fields now interprets interval properly (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
arnaud-moncel authored Dec 18, 2024
1 parent e630744 commit 9e359b9
Show file tree
Hide file tree
Showing 3 changed files with 319 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import patternTransforms from './transforms/pattern';
import timeTransforms from './transforms/time';
import { ColumnType, PrimitiveTypes } from '../../schema';

export type Replacer = (leaf: ConditionTreeLeaf, timezone: string) => ConditionTree;
export type Replacer = (
leaf: ConditionTreeLeaf,
timezone: string,
isDateOnly?: boolean,
) => ConditionTree;

export type Alternative = {
dependsOn: Operator[];
Expand All @@ -29,7 +33,7 @@ export default class ConditionTreeEquivalent {

if (!replacer) return leaf;

return replacer ? replacer(leaf, timezone) : null;
return replacer ? replacer(leaf, timezone, columnType === 'Dateonly') : null;
}

static hasEquivalentTree(
Expand Down Expand Up @@ -59,9 +63,9 @@ export default class ConditionTreeEquivalent {
});

if (dependsReplacers.every(r => !!r)) {
return (leaf, timezone) =>
replacer(leaf, timezone).replaceLeafs(subLeaf =>
dependsReplacers[dependsOn.indexOf(subLeaf.operator)](subLeaf, timezone),
return (leaf, timezone, isDateOnly) =>
replacer(leaf, timezone, isDateOnly).replaceLeafs(subLeaf =>
dependsReplacers[dependsOn.indexOf(subLeaf.operator)](subLeaf, timezone, isDateOnly),
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,37 @@ import { Operator } from '../nodes/operators';

type DateCallback = (now: DateTime, value: unknown) => DateTime;

function format(value: DateTime): string {
function format(value: DateTime, isDateOnly: boolean): string {
if (isDateOnly) return value.toISODate();

return value.toUTC().toISO({ suppressMilliseconds: true });
}

function compare(operator: Operator, dateFn: DateCallback): Alternative {
return {
dependsOn: [operator],
forTypes: ['Date', 'Dateonly'],
replacer: (leaf, tz) => {
replacer: (leaf, tz, isDateOnly) => {
const now = DateTime.utc().setZone(tz);

return leaf.override({ operator, value: format(dateFn(now, leaf.value)) });
return leaf.override({ operator, value: format(dateFn(now, leaf.value), isDateOnly) });
},
};
}

function interval(startFn: DateCallback, endFn: DateCallback): Alternative {
return {
dependsOn: ['LessThan', 'GreaterThan'],
dependsOn: ['LessThan', 'GreaterThan', 'GreaterThanOrEqual'],
forTypes: ['Date', 'Dateonly'],
replacer: (leaf, tz) => {
replacer: (leaf, tz, isDateOnly) => {
const now = DateTime.utc().setZone(tz);

return ConditionTreeFactory.intersect(
leaf.override({ operator: 'GreaterThan', value: format(startFn(now, leaf.value)) }),
leaf.override({ operator: 'LessThan', value: format(endFn(now, leaf.value)) }),
leaf.override({
operator: isDateOnly ? 'GreaterThanOrEqual' : 'GreaterThan',
value: format(startFn(now, leaf.value), isDateOnly),
}),
leaf.override({ operator: 'LessThan', value: format(endFn(now, leaf.value), isDateOnly) }),
);
},
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import ConditionTreeLeaf from '../../../src/interfaces/query/condition-tree/nodes/leaf';
import makeAlternatives from '../../../src/interfaces/query/condition-tree/transforms/time';

describe('ConditionTreeOperators > Time > DateOnly', () => {
const alternatives = makeAlternatives();

beforeAll(() => {
// https://static.wikia.nocookie.net/bttf/images/d/d5/Time_Circuits_BTTF.png
const date = new Date('2024-12-17T23:00:00-00:00');
jest.useFakeTimers().setSystemTime(date);
});

describe('Before', () => {
test('should rewrite', () => {
expect(
alternatives.Before![0].replacer(
new ConditionTreeLeaf('column', 'Before', '2010-01-01'),
'Europe/Paris',
true,
),
).toEqual({
field: 'column',
operator: 'LessThan',
value: '2010-01-01',
});
});
});

describe('After', () => {
test('should rewrite', () => {
expect(
alternatives.After![0].replacer(
new ConditionTreeLeaf('column', 'After', '2010-01-01'),
'Europe/Paris',
true,
),
).toEqual({
field: 'column',
operator: 'GreaterThan',
value: '2010-01-01',
});
});
});

describe('Past', () => {
test('should rewrite', () => {
expect(
alternatives.Past![0].replacer(
new ConditionTreeLeaf('column', 'Past'),
'Europe/Paris',
true,
),
).toEqual({
field: 'column',
operator: 'LessThan',
value: '2024-12-18',
});
});
});

describe('Future', () => {
test('should rewrite', () => {
expect(
alternatives.Future![0].replacer(
new ConditionTreeLeaf('column', 'Future'),
'Europe/Paris',
true,
),
).toEqual({
field: 'column',
operator: 'GreaterThan',
value: '2024-12-18',
});
});
});

describe('PreviousMonthToDate', () => {
test('should rewrite', () => {
expect(
alternatives.PreviousMonthToDate![0].replacer(
new ConditionTreeLeaf('column', 'PreviousMonthToDate'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-12-01' },
{ field: 'column', operator: 'LessThan', value: '2024-12-18' },
],
});
});
});

describe('PreviousMonth', () => {
test('should rewrite', () => {
expect(
alternatives.PreviousMonth![0].replacer(
new ConditionTreeLeaf('column', 'PreviousMonth'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-11-01' },
{ field: 'column', operator: 'LessThan', value: '2024-12-01' },
],
});
});
});

describe('PreviousQuarterToDate', () => {
test('should rewrite', () => {
expect(
alternatives.PreviousQuarterToDate![0].replacer(
new ConditionTreeLeaf('column', 'PreviousQuarterToDate'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-10-01' },
{ field: 'column', operator: 'LessThan', value: '2024-12-18' },
],
});
});
});

describe('PreviousQuarter', () => {
test('should rewrite', () => {
expect(
alternatives.PreviousQuarter![0].replacer(
new ConditionTreeLeaf('column', 'PreviousQuarter'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-07-01' },
{ field: 'column', operator: 'LessThan', value: '2024-10-01' },
],
});
});
});

describe('PreviousWeekToDate', () => {
test('should rewrite', () => {
expect(
alternatives.PreviousWeekToDate![0].replacer(
new ConditionTreeLeaf('column', 'PreviousWeekToDate'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-12-16' },
{ field: 'column', operator: 'LessThan', value: '2024-12-18' },
],
});
});
});

describe('PreviousWeek', () => {
test('should rewrite', () => {
// Note that luxon always consider weeks to be from monday to friday
// @see https://github.com/moment/luxon/issues/373#issuecomment-441123720

expect(
alternatives.PreviousWeek![0].replacer(
new ConditionTreeLeaf('column', 'PreviousWeek'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-12-09' },
{ field: 'column', operator: 'LessThan', value: '2024-12-16' },
],
});
});
});

describe('PreviousXDaysToDate', () => {
test('should rewrite', () => {
expect(
alternatives.PreviousXDaysToDate![0].replacer(
new ConditionTreeLeaf('column', 'PreviousXDaysToDate', 14),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-12-04' },
{ field: 'column', operator: 'LessThan', value: '2024-12-18' },
],
});
});
});

describe('PreviousXDays', () => {
test('should rewrite', () => {
expect(
alternatives.PreviousXDays![0].replacer(
new ConditionTreeLeaf('column', 'PreviousXDays', 14),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-12-04' },
{ field: 'column', operator: 'LessThan', value: '2024-12-18' },
],
});
});
});

describe('PreviousYearToDate', () => {
test('should rewrite', () => {
expect(
alternatives.PreviousYearToDate![0].replacer(
new ConditionTreeLeaf('column', 'PreviousYearToDate'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-01-01' },
{ field: 'column', operator: 'LessThan', value: '2024-12-18' },
],
});
});
});

describe('PreviousYear', () => {
test('should rewrite', () => {
// Notice daylight saving time in this test, as it's january

expect(
alternatives.PreviousYear![0].replacer(
new ConditionTreeLeaf('column', 'PreviousYear'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2023-01-01' },
{ field: 'column', operator: 'LessThan', value: '2024-01-01' },
],
});
});
});

describe('Today', () => {
test('should rewrite', () => {
expect(
alternatives.Today![0].replacer(
new ConditionTreeLeaf('column', 'Today'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-12-18' },
{ field: 'column', operator: 'LessThan', value: '2024-12-19' },
],
});
});
});

describe('Yesterday', () => {
test('should rewrite', () => {
expect(
alternatives.Yesterday![0].replacer(
new ConditionTreeLeaf('column', 'Yesterday'),
'Europe/Paris',
true,
),
).toEqual({
aggregator: 'And',
conditions: [
{ field: 'column', operator: 'GreaterThanOrEqual', value: '2024-12-17' },
{ field: 'column', operator: 'LessThan', value: '2024-12-18' },
],
});
});
});
});

0 comments on commit 9e359b9

Please sign in to comment.