diff --git a/src/utils/viewFilters.test.ts b/src/utils/viewFilters.test.ts index 4454c12a..61dfbb4b 100644 --- a/src/utils/viewFilters.test.ts +++ b/src/utils/viewFilters.test.ts @@ -190,4 +190,58 @@ describe('evaluateView', () => { const result = evaluateView(view, entries) expect(result.map((e) => e.title)).toEqual(['Exact']) }) + + it('before operator works with ISO date strings in properties', () => { + const view: ViewDefinition = { + name: 'Before', icon: null, color: null, sort: null, + filters: { all: [{ field: 'Date', op: 'before', value: '2024-06-01' }] }, + } + const entries = [ + makeEntry({ title: 'Early', properties: { Date: '2024-03-15' } }), + makeEntry({ title: 'Late', properties: { Date: '2024-09-01' } }), + makeEntry({ title: 'NoDate', properties: {} }), + ] + const result = evaluateView(view, entries) + expect(result.map((e) => e.title)).toEqual(['Early']) + }) + + it('after operator works with ISO date strings in properties', () => { + const view: ViewDefinition = { + name: 'After', icon: null, color: null, sort: null, + filters: { all: [{ field: 'Date', op: 'after', value: '2024-06-01' }] }, + } + const entries = [ + makeEntry({ title: 'Early', properties: { Date: '2024-03-15' } }), + makeEntry({ title: 'Late', properties: { Date: '2024-09-01' } }), + ] + const result = evaluateView(view, entries) + expect(result.map((e) => e.title)).toEqual(['Late']) + }) + + it('before/after works with ISO datetime strings', () => { + const view: ViewDefinition = { + name: 'Before datetime', icon: null, color: null, sort: null, + filters: { all: [{ field: 'Date', op: 'before', value: '2024-03-15T12:00:00' }] }, + } + const entries = [ + makeEntry({ title: 'Morning', properties: { Date: '2024-03-15T08:00:00' } }), + makeEntry({ title: 'Evening', properties: { Date: '2024-03-15T18:00:00' } }), + ] + const result = evaluateView(view, entries) + expect(result.map((e) => e.title)).toEqual(['Morning']) + }) + + it('before/after works with numeric Unix timestamps', () => { + const view: ViewDefinition = { + name: 'After ts', icon: null, color: null, sort: null, + filters: { all: [{ field: 'Date', op: 'after', value: '2024-01-01' }] }, + } + // Unix timestamp for 2024-06-15 in seconds + const ts = Math.floor(new Date('2024-06-15').getTime() / 1000) + const entries = [ + makeEntry({ title: 'Match', properties: { Date: ts } }), + ] + const result = evaluateView(view, entries) + expect(result.map((e) => e.title)).toEqual(['Match']) + }) }) diff --git a/src/utils/viewFilters.ts b/src/utils/viewFilters.ts index 7423e79d..ab205299 100644 --- a/src/utils/viewFilters.ts +++ b/src/utils/viewFilters.ts @@ -104,11 +104,17 @@ function evaluateCondition(cond: FilterCondition, entry: VaultEntry): boolean { // Date comparisons if (op === 'before' || op === 'after') { - const ts = typeof resolved.scalar === 'number' ? resolved.scalar : null - if (!ts) return false - const target = Date.parse(condVal) / 1000 + let tsMs: number | null = null + if (typeof resolved.scalar === 'number') { + tsMs = resolved.scalar * 1000 // Unix timestamp (seconds) → milliseconds + } else if (typeof resolved.scalar === 'string') { + const parsed = Date.parse(resolved.scalar) + tsMs = isNaN(parsed) ? null : parsed + } + if (tsMs == null) return false + const target = Date.parse(condVal) if (isNaN(target)) return false - return op === 'before' ? ts < target : ts > target + return op === 'before' ? tsMs < target : tsMs > target } return false