From 9e2879c0ba5021b1127586ad3b4ab1dde6d730cc Mon Sep 17 00:00:00 2001 From: Rudy Celekli Date: Fri, 23 Oct 2026 19:08:52 -0400 Subject: [PATCH] fix(kartaview): reject impossible photo timestamps Co-authored-by: Cursor --- .../streetLevel/providers/kartaview/policy.js | 29 +++++++++++++++++-- .../providers/kartaview/policy.test.mjs | 4 +++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/layers/streetLevel/providers/kartaview/policy.js b/src/layers/streetLevel/providers/kartaview/policy.js index b4533c1b5..76a0ea208 100644 --- a/src/layers/streetLevel/providers/kartaview/policy.js +++ b/src/layers/streetLevel/providers/kartaview/policy.js @@ -222,9 +222,32 @@ export function kartaViewTimeMs(value) { String(value ?? ''), ); if (!match) return null; - const [, y, mo, d, h = '0', mi = '0', s = '0'] = match; - if (Number(y) < 1990) return null; - const ms = Date.UTC(+y, +mo - 1, +d, +h, +mi, +s); + const year = Number(match[1]); + const month = Number(match[2]); + const day = Number(match[3]); + const hours = Number(match[4] ?? 0); + const minutes = Number(match[5] ?? 0); + const seconds = Number(match[6] ?? 0); + if (year < 1990) return null; + if ( + month < 1 || + month > 12 || + day < 1 || + hours > 23 || + minutes > 59 || + seconds > 59 + ) + return null; + // Date.UTC rolls 31 February into March. A photo would then pass or fail + // the day filter on the wrong calendar day, so an impossible date is unknown. + const ms = Date.UTC(year, month - 1, day, hours, minutes, seconds); + const parsed = new Date(ms); + if ( + parsed.getUTCFullYear() !== year || + parsed.getUTCMonth() !== month - 1 || + parsed.getUTCDate() !== day + ) + return null; return Number.isFinite(ms) ? ms : null; } diff --git a/src/layers/streetLevel/providers/kartaview/policy.test.mjs b/src/layers/streetLevel/providers/kartaview/policy.test.mjs index 82a68555e..540071f0b 100644 --- a/src/layers/streetLevel/providers/kartaview/policy.test.mjs +++ b/src/layers/streetLevel/providers/kartaview/policy.test.mjs @@ -158,6 +158,10 @@ test('timestamps parse as UTC; years before 1990 and garbage are unknown', () => kartaViewTimeMs('2022-03-21T06:42:59'), Date.UTC(2022, 2, 21, 6, 42, 59), ); + assert.equal(kartaViewTimeMs('2022-02-31 12:00:00'), null); + assert.equal(kartaViewTimeMs('2022-13-01 00:00:00'), null); + assert.equal(kartaViewTimeMs('2022-03-21 25:00:00'), null); + assert.equal(kartaViewTimeMs('2022-04-31'), null); assert.equal(kartaViewTimeMs('0000-00-00 00:00:00'), null); assert.equal(kartaViewTimeMs(''), null); assert.equal(kartaViewTimeMs(null), null);