From 28e601553d908db9453d56d1490c79e7530ab842 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Mon, 18 Dec 2017 23:25:41 +0100 Subject: [PATCH 1/4] =?UTF-8?q?fix=20DB=20modes=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- p/db/modes.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/p/db/modes.js b/p/db/modes.js index be2252c3..cdd63eae 100644 --- a/p/db/modes.js +++ b/p/db/modes.js @@ -17,15 +17,15 @@ const m = { }, regionalExp: { bitmask: 4, - name: 'InterRegio', - short: 'IR', + name: 'RegionalExpress & InterRegio', + short: 'RE/IR', mode: 'train', product: 'regionalExp' }, regional: { bitmask: 8, - name: 'RegionalExpress & Regio', - short: 'RE/RB', + name: 'Regio', + short: 'RB', mode: 'train', product: 'regional' }, From c304119de539591b022c74c95921dad6bebf05d3 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Mon, 18 Dec 2017 23:33:29 +0100 Subject: [PATCH 2/4] =?UTF-8?q?bugfixes=20=F0=9F=90=9B=F0=9F=92=9A,=20upda?= =?UTF-8?q?te=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- p/db/modes.js | 1 + package.json | 4 ++-- parse/departure.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/p/db/modes.js b/p/db/modes.js index cdd63eae..6996b768 100644 --- a/p/db/modes.js +++ b/p/db/modes.js @@ -1,5 +1,6 @@ 'use strict' +// todo: https://gist.github.com/anonymous/d3323a5d2d6e159ed42b12afd0380434#file-haf_products-properties-L1-L95 const m = { nationalExp: { bitmask: 1, diff --git a/package.json b/package.json index 3437284b..83856381 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "vbb-parse-line": "^0.2.5", "vbb-parse-ticket": "^0.2.1", "vbb-short-station-name": "^0.4.0", - "vbb-stations": "^5.8.0", + "vbb-stations": "^5.9.0", "vbb-translate-ids": "^3.1.0" }, "devDependencies": { @@ -49,7 +49,7 @@ "tape": "^4.8.0", "tape-promise": "^2.0.1", "validate-fptf": "^1.0.2", - "vbb-stations-autocomplete": "^2.9.0" + "vbb-stations-autocomplete": "^2.11.0" }, "scripts": { "test": "node test/index.js", diff --git a/parse/departure.js b/parse/departure.js index 1db0f914..a4fce0dd 100644 --- a/parse/departure.js +++ b/parse/departure.js @@ -30,7 +30,7 @@ const createParseDeparture = (profile, stations, lines, remarks) => { // todo: follow public-transport/friendly-public-transport-format#27 here // see also derhuerst/vbb-rest#19 - if (pt.arr.aCncl || pt.dep.dCncl) { + if (d.stbStop.aCncl || d.stbStop.dCncl) { res.cancelled = true res.when = res.delay = null } From 8985f8ccd2d8ffa32b09189154174b9c230cc91c Mon Sep 17 00:00:00 2001 From: Jannis R Date: Thu, 28 Dec 2017 16:56:27 +0100 Subject: [PATCH 3/4] rename journey.parts -> journey.legs --- index.js | 10 +++++----- lib/default-profile.js | 6 +++--- lib/validate-profile.js | 2 +- p/vbb/index.js | 2 +- parse/index.js | 2 +- parse/{journey-part.js => journey-leg.js} | 8 ++++---- parse/journey.js | 18 +++++++++--------- 7 files changed, 24 insertions(+), 24 deletions(-) rename parse/{journey-part.js => journey-leg.js} (91%) diff --git a/index.js b/index.js index 93409c1c..616e6a0c 100644 --- a/index.js +++ b/index.js @@ -169,7 +169,7 @@ const createClient = (profile) => { }) } - const journeyPart = (ref, lineName, opt = {}) => { + const journeyLeg = (ref, lineName, opt = {}) => { opt = Object.assign({ passedStations: true // return stations on the way? }, opt) @@ -185,15 +185,15 @@ const createClient = (profile) => { } }) .then((d) => { - const parse = profile.parseJourneyPart(profile, d.locations, d.lines, d.remarks) + const parse = profile.parseJourneyLeg(profile, d.locations, d.lines, d.remarks) - const part = { // pretend the part is contained in a journey + const leg = { // pretend the leg is contained in a journey type: 'JNY', dep: minBy(d.journey.stopL, 'idx'), arr: maxBy(d.journey.stopL, 'idx'), jny: d.journey } - return parse(d.journey, part, !!opt.passedStations) + return parse(d.journey, leg, !!opt.passedStations) }) } @@ -239,7 +239,7 @@ const createClient = (profile) => { } const client = {departures, journeys, locations, nearby} - if (profile.journeyPart) client.journeyPart = journeyPart + if (profile.journeyLeg) client.journeyLeg = journeyLeg if (profile.radar) client.radar = radar Object.defineProperty(client, 'profile', {value: profile}) return client diff --git a/lib/default-profile.js b/lib/default-profile.js index a26fbb67..ec2a09fe 100644 --- a/lib/default-profile.js +++ b/lib/default-profile.js @@ -2,7 +2,7 @@ const parseDateTime = require('../parse/date-time') const parseDeparture = require('../parse/departure') -const parseJourneyPart = require('../parse/journey-part') +const parseJourneyLeg = require('../parse/journey-leg') const parseJourney = require('../parse/journey') const parseLine = require('../parse/line') const parseLocation = require('../parse/location') @@ -33,7 +33,7 @@ const defaultProfile = { parseDateTime, parseDeparture, - parseJourneyPart, + parseJourneyLeg, parseJourney, parseLine, parseStationName: id, @@ -55,7 +55,7 @@ const defaultProfile = { formatRectangle, filters, - journeyPart: false, + journeyLeg: false, radar: false } diff --git a/lib/validate-profile.js b/lib/validate-profile.js index 7d875c74..cfa8a840 100644 --- a/lib/validate-profile.js +++ b/lib/validate-profile.js @@ -11,7 +11,7 @@ const types = { parseDateTime: 'function', parseDeparture: 'function', - parseJourneyPart: 'function', + parseJourneyLeg: 'function', parseJourney: 'function', parseLine: 'function', parseStationName: 'function', diff --git a/p/vbb/index.js b/p/vbb/index.js index a1018930..dce6261a 100644 --- a/p/vbb/index.js +++ b/p/vbb/index.js @@ -178,7 +178,7 @@ const vbbProfile = { formatStation, formatProducts, - journeyPart: true, + journeyLeg: true, radar: true } diff --git a/parse/index.js b/parse/index.js index af61cf55..11a5bd0f 100644 --- a/parse/index.js +++ b/parse/index.js @@ -7,7 +7,7 @@ module.exports = { remark: require('./remark'), operator: require('./operator'), stopover: require('./stopover'), - journeyPart: require('./journey-part'), + journeyLeg: require('./journey-leg'), journey: require('./journey'), nearby: require('./nearby'), movement: require('./movement') diff --git a/parse/journey-part.js b/parse/journey-leg.js similarity index 91% rename from parse/journey-part.js rename to parse/journey-leg.js index 9d66d792..cf8a4f7a 100644 --- a/parse/journey-part.js +++ b/parse/journey-leg.js @@ -4,7 +4,7 @@ const parseDateTime = require('./date-time') const clone = obj => Object.assign({}, obj) -const createParseJourneyPart = (profile, stations, lines, remarks) => { +const createParseJourneyLeg = (profile, stations, lines, remarks) => { // todo: finish parse/remark.js first const applyRemark = (j, rm) => {} @@ -13,7 +13,7 @@ const createParseJourneyPart = (profile, stations, lines, remarks) => { // todo: what is pt.jny.dirFlg? // todo: how does pt.freq work? // todo: what is pt.himL? - const parseJourneyPart = (j, pt, passed = true) => { // j = journey, pt = part + const parseJourneyLeg = (j, pt, passed = true) => { // j = journey, pt = part const dep = profile.parseDateTime(profile, j.date, pt.dep.dTimeR || pt.dep.dTimeS) const arr = profile.parseDateTime(profile, j.date, pt.arr.aTimeR || pt.arr.aTimeS) const res = { @@ -79,7 +79,7 @@ const createParseJourneyPart = (profile, stations, lines, remarks) => { return res } - return parseJourneyPart + return parseJourneyLeg } -module.exports = createParseJourneyPart +module.exports = createParseJourneyLeg diff --git a/parse/journey.js b/parse/journey.js index 7dc9c737..2463c114 100644 --- a/parse/journey.js +++ b/parse/journey.js @@ -1,26 +1,26 @@ 'use strict' -const createParseJourneyPart = require('./journey-part') +const createParseJourneyLeg = require('./journey-leg') const clone = obj => Object.assign({}, obj) const createParseJourney = (profile, stations, lines, remarks) => { - const parsePart = createParseJourneyPart(profile, stations, lines, remarks) + const parseLeg = createParseJourneyLeg(profile, stations, lines, remarks) // todo: c.sDays // todo: c.dep.dProgType, c.arr.dProgType // todo: c.conSubscr // todo: c.trfRes x vbb-parse-ticket const parseJourney = (j) => { - const parts = j.secL.map(part => parsePart(j, part)) + const legs = j.secL.map(leg => parseLeg(j, leg)) const res = { - parts, - origin: parts[0].origin, - destination: parts[parts.length - 1].destination, - departure: parts[0].departure, - arrival: parts[parts.length - 1].arrival + legs, + origin: legs[0].origin, + destination: legs[legs.length - 1].destination, + departure: legs[0].departure, + arrival: legs[legs.length - 1].arrival } - if (parts.some(p => p.cancelled)) { + if (legs.some(p => p.cancelled)) { res.cancelled = true res.departure = res.arrival = null } From c02983492b72d74d061e1d29971d746c1eec3f64 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Thu, 28 Dec 2017 17:14:53 +0100 Subject: [PATCH 4/4] =?UTF-8?q?docs,=20tests:=20rename=20journey.parts=20-?= =?UTF-8?q?>=20journey.legs=20=F0=9F=93=9D=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/departures.md | 2 +- docs/{journey-part.md => journey-leg.md} | 8 +-- docs/journeys.md | 2 +- readme.md | 4 +- test/db.js | 72 +++++++++---------- test/vbb.js | 92 ++++++++++++------------ 6 files changed, 90 insertions(+), 90 deletions(-) rename docs/{journey-part.md => journey-leg.md} (92%) diff --git a/docs/departures.md b/docs/departures.md index 6c37a82e..9620331d 100644 --- a/docs/departures.md +++ b/docs/departures.md @@ -33,7 +33,7 @@ With `opt`, you can override the default options, which look like this: *Note:* As stated in the [*Friendly Public Transport Format* `1.0.1`](https://github.com/public-transport/friendly-public-transport-format/tree/1.0.1), the `when` include the current delay. The `delay` field, if present, expresses how much the former differs from the schedule. -You may pass the `journeyId` field into [`journeyPart(ref, lineName, [opt])`](journey-part.md) to get details on the vehicle's journey. +You may pass the `journeyId` field into [`journeyLeg(ref, lineName, [opt])`](journey-leg.md) to get details on the vehicle's journey. As an example, we're going to use the VBB profile: diff --git a/docs/journey-part.md b/docs/journey-leg.md similarity index 92% rename from docs/journey-part.md rename to docs/journey-leg.md index faba512e..9538199f 100644 --- a/docs/journey-part.md +++ b/docs/journey-leg.md @@ -1,4 +1,4 @@ -# `journeyPart(ref, lineName, [opt])` +# `journeyLeg(ref, lineName, [opt])` This method can be used to refetch information about a leg of a journey. Note that it is not supported by every profile/endpoint. @@ -13,8 +13,8 @@ const client = createClient(vbbProfile) // Hauptbahnhof to Heinrich-Heine-Str. client.journeys('900000003201', '900000100008', {results: 1}) .then(([journey]) => { - const part = journey.parts[0] - return client.journeyPart(part.id, part.line.name) + const leg = journey.legs[0] + return client.journeyLeg(leg.id, leg.line.name) }) .then(console.log) .catch(console.error) @@ -41,7 +41,7 @@ const vbbProfile = require('hafas-client/p/vbb') const client = createClient(vbbProfile) -client.journeyPart('1|31431|28|86|17122017', 'S9', {when: 1513534689273}) +client.journeyLeg('1|31431|28|86|17122017', 'S9', {when: 1513534689273}) .then(console.log) .catch(console.error) ``` diff --git a/docs/journeys.md b/docs/journeys.md index 4617936d..98cca95e 100644 --- a/docs/journeys.md +++ b/docs/journeys.md @@ -86,7 +86,7 @@ The response may look like this: ```js [ { - parts: [ { + legs: [ { id: '1|31041|35|86|17122017', origin: { type: 'station', diff --git a/readme.md b/readme.md index 86249212..23840a56 100644 --- a/readme.md +++ b/readme.md @@ -28,7 +28,7 @@ npm install hafas-client ## API - [`journeys(from, to, [opt])`](docs/journeys.md) – get journeys between locations -- [`journeyPart(ref, name, [opt])`](docs/journey-part.md) – get details for a part of a journey +- [`journeyLeg(ref, name, [opt])`](docs/journey-leg.md) – get details for a leg of a journey - [`departures(station, [opt])`](docs/departures.md) – query the next departures at a station - [`locations(query, [opt])`](docs/locations.md) – find stations, POIs and addresses - [`nearby(latitude, longitude, [opt])`](docs/nearby.md) – show stations & POIs around @@ -54,7 +54,7 @@ The returned [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript ```js [ { - parts: [ { + legs: [ { id: '1|100067|48|81|17122017', origin: { type: 'station', diff --git a/test/db.js b/test/db.js index 35292b12..317b3c65 100644 --- a/test/db.js +++ b/test/db.js @@ -118,30 +118,30 @@ test('Berlin Jungfernheide to München Hbf', co.wrap(function* (t) { } t.ok(isValidWhen(journey.arrival)) - t.ok(Array.isArray(journey.parts)) - t.ok(journey.parts.length > 0, 'no parts') - const part = journey.parts[0] + t.ok(Array.isArray(journey.legs)) + t.ok(journey.legs.length > 0, 'no legs') + const leg = journey.legs[0] - assertValidStation(t, part.origin) - assertValidStationProducts(t, part.origin.products) - if (!(yield findStation(part.origin.id))) { - console.error('unknown station', part.origin.id, part.origin.name) + assertValidStation(t, leg.origin) + assertValidStationProducts(t, leg.origin.products) + if (!(yield findStation(leg.origin.id))) { + console.error('unknown station', leg.origin.id, leg.origin.name) } - t.ok(isValidWhen(part.departure)) - t.equal(typeof part.departurePlatform, 'string') + t.ok(isValidWhen(leg.departure)) + t.equal(typeof leg.departurePlatform, 'string') - assertValidStation(t, part.destination) - assertValidStationProducts(t, part.origin.products) - if (!(yield findStation(part.destination.id))) { - console.error('unknown station', part.destination.id, part.destination.name) + assertValidStation(t, leg.destination) + assertValidStationProducts(t, leg.origin.products) + if (!(yield findStation(leg.destination.id))) { + console.error('unknown station', leg.destination.id, leg.destination.name) } - t.ok(isValidWhen(part.arrival)) - t.equal(typeof part.arrivalPlatform, 'string') + t.ok(isValidWhen(leg.arrival)) + t.equal(typeof leg.arrivalPlatform, 'string') - assertValidLine(t, part.line) + assertValidLine(t, leg.line) - t.ok(Array.isArray(part.passed)) - for (let stopover of part.passed) assertValidStopover(t, stopover) + t.ok(Array.isArray(leg.passed)) + for (let stopover of leg.passed) assertValidStopover(t, stopover) if (journey.price) assertValidPrice(t, journey.price) } @@ -158,18 +158,18 @@ test('Berlin Jungfernheide to Torfstraße 17', co.wrap(function* (t) { t.ok(Array.isArray(journeys)) t.ok(journeys.length >= 1, 'no journeys') const journey = journeys[0] - const part = journey.parts[journey.parts.length - 1] + const leg = journey.legs[journey.legs.length - 1] - assertValidStation(t, part.origin) - assertValidStationProducts(t, part.origin.products) - if (!(yield findStation(part.origin.id))) { - console.error('unknown station', part.origin.id, part.origin.name) + assertValidStation(t, leg.origin) + assertValidStationProducts(t, leg.origin.products) + if (!(yield findStation(leg.origin.id))) { + console.error('unknown station', leg.origin.id, leg.origin.name) } - if (part.origin.products) assertValidProducts(t, part.origin.products) - t.ok(isValidWhen(part.departure)) - t.ok(isValidWhen(part.arrival)) + if (leg.origin.products) assertValidProducts(t, leg.origin.products) + t.ok(isValidWhen(leg.departure)) + t.ok(isValidWhen(leg.arrival)) - const d = part.destination + const d = leg.destination assertValidAddress(t, d) t.equal(d.address, 'Torfstraße 17') t.ok(isRoughlyEqual(.0001, d.latitude, 52.5416823)) @@ -187,18 +187,18 @@ test('Berlin Jungfernheide to ATZE Musiktheater', co.wrap(function* (t) { t.ok(Array.isArray(journeys)) t.ok(journeys.length >= 1, 'no journeys') const journey = journeys[0] - const part = journey.parts[journey.parts.length - 1] + const leg = journey.legs[journey.legs.length - 1] - assertValidStation(t, part.origin) - assertValidStationProducts(t, part.origin.products) - if (!(yield findStation(part.origin.id))) { - console.error('unknown station', part.origin.id, part.origin.name) + assertValidStation(t, leg.origin) + assertValidStationProducts(t, leg.origin.products) + if (!(yield findStation(leg.origin.id))) { + console.error('unknown station', leg.origin.id, leg.origin.name) } - if (part.origin.products) assertValidProducts(t, part.origin.products) - t.ok(isValidWhen(part.departure)) - t.ok(isValidWhen(part.arrival)) + if (leg.origin.products) assertValidProducts(t, leg.origin.products) + t.ok(isValidWhen(leg.departure)) + t.ok(isValidWhen(leg.arrival)) - const d = part.destination + const d = leg.destination assertValidPoi(t, d) t.equal(d.name, 'ATZE Musiktheater') t.ok(isRoughlyEqual(.0001, d.latitude, 52.542399)) diff --git a/test/vbb.js b/test/vbb.js index fb0676b5..cc9eec9d 100644 --- a/test/vbb.js +++ b/test/vbb.js @@ -77,29 +77,29 @@ test('journeys – station to station', co.wrap(function* (t) { t.strictEqual(journey.destination.id, amrumerStr) assertValidWhen(t, journey.arrival) - t.ok(Array.isArray(journey.parts)) - t.strictEqual(journey.parts.length, 1) - const part = journey.parts[0] + t.ok(Array.isArray(journey.legs)) + t.strictEqual(journey.legs.length, 1) + const leg = journey.legs[0] - t.equal(typeof part.id, 'string') - t.ok(part.id) - assertValidStation(t, part.origin) - assertValidStationProducts(t, part.origin.products) - t.ok(part.origin.name.indexOf('(Berlin)') === -1) - t.strictEqual(part.origin.id, spichernstr) - assertValidWhen(t, part.departure) + t.equal(typeof leg.id, 'string') + t.ok(leg.id) + assertValidStation(t, leg.origin) + assertValidStationProducts(t, leg.origin.products) + t.ok(leg.origin.name.indexOf('(Berlin)') === -1) + t.strictEqual(leg.origin.id, spichernstr) + assertValidWhen(t, leg.departure) - assertValidStation(t, part.destination) - assertValidStationProducts(t, part.destination.products) - t.strictEqual(part.destination.id, amrumerStr) - assertValidWhen(t, part.arrival) + assertValidStation(t, leg.destination) + assertValidStationProducts(t, leg.destination.products) + t.strictEqual(leg.destination.id, amrumerStr) + assertValidWhen(t, leg.arrival) - assertValidLine(t, part.line) - t.ok(findStation(part.direction)) - t.ok(part.direction.indexOf('(Berlin)') === -1) + assertValidLine(t, leg.line) + t.ok(findStation(leg.direction)) + t.ok(leg.direction.indexOf('(Berlin)') === -1) - t.ok(Array.isArray(part.passed)) - for (let passed of part.passed) assertValidStopover(t, passed) + t.ok(Array.isArray(leg.passed)) + for (let passed of leg.passed) assertValidStopover(t, passed) // todo: find a journey where there ticket info is always available if (journey.tickets) { @@ -128,11 +128,11 @@ test('journeys – only subway', co.wrap(function* (t) { t.ok(journeys.length > 1) for (let journey of journeys) { - for (let part of journey.parts) { - if (part.line) { - assertValidLine(t, part.line) - t.equal(part.line.mode, 'train') - t.equal(part.line.product, 'subway') + for (let leg of journey.legs) { + if (leg.line) { + assertValidLine(t, leg.line) + t.equal(leg.line.mode, 'train') + t.equal(leg.line.product, 'subway') } } } @@ -159,26 +159,26 @@ test('journeys – fails with no product', co.wrap(function* (t) { } })) -test('journey part details', co.wrap(function* (t) { +test('journey leg details', co.wrap(function* (t) { const journeys = yield client.journeys(spichernstr, amrumerStr, { results: 1, when }) - const p = journeys[0].parts[0] + const p = journeys[0].legs[0] t.ok(p.id, 'precondition failed') t.ok(p.line.name, 'precondition failed') - const part = yield client.journeyPart(p.id, p.line.name, {when}) + const leg = yield client.journeyLeg(p.id, p.line.name, {when}) - t.equal(typeof part.id, 'string') - t.ok(part.id) + t.equal(typeof leg.id, 'string') + t.ok(leg.id) - assertValidLine(t, part.line) + assertValidLine(t, leg.line) - t.equal(typeof part.direction, 'string') - t.ok(part.direction) + t.equal(typeof leg.direction, 'string') + t.ok(leg.direction) - t.ok(Array.isArray(part.passed)) - for (let passed of part.passed) assertValidStopover(t, passed) + t.ok(Array.isArray(leg.passed)) + for (let passed of leg.passed) assertValidStopover(t, passed) t.end() })) @@ -194,18 +194,18 @@ test('journeys – station to address', co.wrap(function* (t) { t.ok(Array.isArray(journeys)) t.strictEqual(journeys.length, 1) const journey = journeys[0] - const part = journey.parts[journey.parts.length - 1] + const leg = journey.legs[journey.legs.length - 1] - assertValidStation(t, part.origin) - assertValidStationProducts(t, part.origin.products) - assertValidWhen(t, part.departure) + assertValidStation(t, leg.origin) + assertValidStationProducts(t, leg.origin.products) + assertValidWhen(t, leg.departure) - const dest = part.destination + const dest = leg.destination assertValidAddress(t, dest) t.strictEqual(dest.address, 'Torfstraße 17') t.ok(isRoughlyEqual(.0001, dest.latitude, 52.5416823)) t.ok(isRoughlyEqual(.0001, dest.longitude, 13.3491223)) - assertValidWhen(t, part.arrival) + assertValidWhen(t, leg.arrival) t.end() })) @@ -221,18 +221,18 @@ test('journeys – station to POI', co.wrap(function* (t) { t.ok(Array.isArray(journeys)) t.strictEqual(journeys.length, 1) const journey = journeys[0] - const part = journey.parts[journey.parts.length - 1] + const leg = journey.legs[journey.legs.length - 1] - assertValidStation(t, part.origin) - assertValidStationProducts(t, part.origin.products) - assertValidWhen(t, part.departure) + assertValidStation(t, leg.origin) + assertValidStationProducts(t, leg.origin.products) + assertValidWhen(t, leg.departure) - const dest = part.destination + const dest = leg.destination assertValidPoi(t, dest) t.strictEqual(dest.name, 'ATZE Musiktheater') t.ok(isRoughlyEqual(.0001, dest.latitude, 52.543333)) t.ok(isRoughlyEqual(.0001, dest.longitude, 13.351686)) - assertValidWhen(t, part.arrival) + assertValidWhen(t, leg.arrival) t.end() }))