Fix 'invalid date' display for ISO datetime resolution_date values
The pg driver returns PostgreSQL DATE columns as ISO datetime strings (e.g. '2026-07-03T00:00:00.000Z'). The formatResolutionDate helper was strictly matching YYYY-MM-DD only, so these were classified as 'invalid'. Now the helper extracts the date prefix from ISO datetime strings before validating, correctly classifying them as 'set' with the YYYY-MM-DD value. Updated the property test filter and added an example test for the case.
This commit is contained in:
@@ -43,6 +43,14 @@ function isValidCalendarYmd(s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// True iff `s` is an ISO datetime string whose date prefix is a valid calendar date.
|
||||
// e.g. "2026-07-01T00:00:00.000Z" → true (the helper now extracts the date prefix).
|
||||
function isIsoDateTimeWithValidDate(s) {
|
||||
if (typeof s !== 'string') return false;
|
||||
if (!/^\d{4}-\d{2}-\d{2}T/.test(s)) return false;
|
||||
return isValidCalendarYmd(s.slice(0, 10));
|
||||
}
|
||||
|
||||
// --- Shared arbitraries -----------------------------------------------------
|
||||
|
||||
// Four-digit zero-padded year string (0000–9999) — always matches \d{4}.
|
||||
@@ -130,7 +138,7 @@ const wrongShapeArb = fc.oneof(
|
||||
|
||||
const invalidStringArb = fc
|
||||
.oneof(wrongShapeArb, badMonthArb, badDayArb, impossibleDayArb, twoDigitArb)
|
||||
.filter(s => typeof s === 'string' && s.trim() !== '' && !isValidCalendarYmd(s.trim()));
|
||||
.filter(s => typeof s === 'string' && s.trim() !== '' && !isValidCalendarYmd(s.trim()) && !isIsoDateTimeWithValidDate(s.trim()));
|
||||
|
||||
// Any input category (used for totality / independence properties).
|
||||
const anyInputArb = fc.oneof(
|
||||
|
||||
@@ -32,6 +32,13 @@ describe('formatResolutionDate', () => {
|
||||
value: '2024-02-29',
|
||||
});
|
||||
});
|
||||
|
||||
it("classifies an ISO datetime '2026-07-03T00:00:00.000Z' as set with the date prefix", () => {
|
||||
expect(formatResolutionDate('2026-07-03T00:00:00.000Z')).toEqual({
|
||||
state: 'set',
|
||||
value: '2026-07-03',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('invalid — present but not a valid calendar date (Requirement 1.6)', () => {
|
||||
|
||||
@@ -63,14 +63,20 @@ export function formatResolutionDate(raw) {
|
||||
}
|
||||
|
||||
// Must match the strict YYYY-MM-DD shape.
|
||||
if (!YMD_SHAPE.test(trimmed)) {
|
||||
// Also accept ISO datetime strings (e.g. "2026-07-03T00:00:00.000Z") by
|
||||
// extracting the date prefix — the pg driver returns DATE columns this way.
|
||||
let candidate = trimmed;
|
||||
if (!YMD_SHAPE.test(candidate) && /^\d{4}-\d{2}-\d{2}T/.test(candidate)) {
|
||||
candidate = candidate.slice(0, 10);
|
||||
}
|
||||
if (!YMD_SHAPE.test(candidate)) {
|
||||
return { state: 'invalid' };
|
||||
}
|
||||
|
||||
// Shape is correct; verify it is a real calendar date.
|
||||
const year = Number(trimmed.slice(0, 4));
|
||||
const month = Number(trimmed.slice(5, 7));
|
||||
const day = Number(trimmed.slice(8, 10));
|
||||
const year = Number(candidate.slice(0, 4));
|
||||
const month = Number(candidate.slice(5, 7));
|
||||
const day = Number(candidate.slice(8, 10));
|
||||
|
||||
if (month < 1 || month > 12) {
|
||||
return { state: 'invalid' };
|
||||
@@ -80,7 +86,7 @@ export function formatResolutionDate(raw) {
|
||||
return { state: 'invalid' };
|
||||
}
|
||||
|
||||
// Valid calendar date; the trimmed value is already the canonical
|
||||
// Valid calendar date; the candidate value is the canonical
|
||||
// zero-padded YYYY-MM-DD form.
|
||||
return { state: 'set', value: trimmed };
|
||||
return { state: 'set', value: candidate };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user