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:
Jordan Ramos
2026-06-02 14:12:13 -06:00
parent aae09020e6
commit c5225c96a5
3 changed files with 28 additions and 7 deletions

View File

@@ -43,6 +43,14 @@ function isValidCalendarYmd(s) {
return true; 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 ----------------------------------------------------- // --- Shared arbitraries -----------------------------------------------------
// Four-digit zero-padded year string (00009999) — always matches \d{4}. // Four-digit zero-padded year string (00009999) — always matches \d{4}.
@@ -130,7 +138,7 @@ const wrongShapeArb = fc.oneof(
const invalidStringArb = fc const invalidStringArb = fc
.oneof(wrongShapeArb, badMonthArb, badDayArb, impossibleDayArb, twoDigitArb) .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). // Any input category (used for totality / independence properties).
const anyInputArb = fc.oneof( const anyInputArb = fc.oneof(

View File

@@ -32,6 +32,13 @@ describe('formatResolutionDate', () => {
value: '2024-02-29', 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)', () => { describe('invalid — present but not a valid calendar date (Requirement 1.6)', () => {

View File

@@ -63,14 +63,20 @@ export function formatResolutionDate(raw) {
} }
// Must match the strict YYYY-MM-DD shape. // 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' }; return { state: 'invalid' };
} }
// Shape is correct; verify it is a real calendar date. // Shape is correct; verify it is a real calendar date.
const year = Number(trimmed.slice(0, 4)); const year = Number(candidate.slice(0, 4));
const month = Number(trimmed.slice(5, 7)); const month = Number(candidate.slice(5, 7));
const day = Number(trimmed.slice(8, 10)); const day = Number(candidate.slice(8, 10));
if (month < 1 || month > 12) { if (month < 1 || month > 12) {
return { state: 'invalid' }; return { state: 'invalid' };
@@ -80,7 +86,7 @@ export function formatResolutionDate(raw) {
return { state: 'invalid' }; 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. // zero-padded YYYY-MM-DD form.
return { state: 'set', value: trimmed }; return { state: 'set', value: candidate };
} }