fix(transport): guard non-finite dates in trip-map duration

This commit is contained in:
Konstantinos Thermos
2026-07-24 10:22:35 +03:00
committed by Maurice
parent 7bd9e08016
commit fce26618a1
3 changed files with 32 additions and 0 deletions
@@ -83,6 +83,11 @@ function parseInTz(isoLocal: string, tz: string): number {
const [y, mo, d] = datePart.split('-').map(Number)
const [h, mi] = (timePart || '00:00').split(':').map(Number)
const guess = Date.UTC(y, mo - 1, d, h, mi)
// A malformed date/time (e.g. an imported booking whose time is missing its
// minutes) makes Date.UTC NaN; bail before formatToParts, which throws on a
// non-finite date and would blank the whole trip. computeDuration's finiteness
// check then drops the duration cleanly.
if (!Number.isFinite(guess)) return NaN
const fmt = new Intl.DateTimeFormat('en-US', {
timeZone: tz, hour12: false,
year: 'numeric', month: '2-digit', day: '2-digit',
@@ -93,6 +93,28 @@ describe('ReservationMapboxOverlay road routes (#1425)', () => {
})
})
// A flight whose endpoints carry a malformed local_time (an imported booking
// missing the minutes) plus timezones, so computeDuration takes the parseInTz
// path. Pre-fix, Date.UTC → NaN and formatToParts threw mid-render (#1620).
function malformedTimeFlight(): Reservation {
return {
id: 3, type: 'flight', status: 'confirmed',
reservation_time: '2024-01-15T22', reservation_end_time: '2024-01-16T08',
endpoints: [
{ role: 'from', sequence: 0, name: 'JFK', code: 'JFK', lat: 40.6, lng: -73.8, timezone: 'America/New_York', local_date: '2024-01-15', local_time: '22' },
{ role: 'to', sequence: 1, name: 'LHR', code: 'LHR', lat: 51.5, lng: -0.5, timezone: 'Europe/London', local_date: '2024-01-16', local_time: '08' },
],
} as unknown as Reservation
}
describe('ReservationMapboxOverlay malformed times (#1620)', () => {
it('renders a flight with a malformed time instead of throwing on formatToParts', () => {
const map = fakeMap()
const overlay = new ReservationMapboxOverlay(map as never, opts, FakeMarker as never)
expect(() => overlay.update([malformedTimeFlight()], opts)).not.toThrow()
})
})
describe('ReservationMapboxOverlay transit routes (#1570)', () => {
it('draws a transit journey with real geometry even when its stations project close together', () => {
const map = fakeMap()
@@ -51,6 +51,11 @@ function parseInTz(isoLocal: string, tz: string): number {
const [y, mo, d] = datePart.split('-').map(Number)
const [h, mi] = (timePart || '00:00').split(':').map(Number)
const guess = Date.UTC(y, mo - 1, d, h, mi)
// A malformed date/time (e.g. an imported booking whose time is missing its
// minutes) makes Date.UTC NaN; bail before formatToParts, which throws on a
// non-finite date and would blank the whole trip. computeDuration's finiteness
// check then drops the duration cleanly.
if (!Number.isFinite(guess)) return NaN
const fmt = new Intl.DateTimeFormat('en-US', {
timeZone: tz, hour12: false,
year: 'numeric', month: '2-digit', day: '2-digit',