-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Expected behavior
In arriveBy searches, trips should only be included if they arrive before or at the specified latestArrivalTime time. For midnight-crossing trips (trips with service dates from the previous day but scheduled times > 24 hours), the actual arrival time should be correctly calculated and compared against the latestArrivalTime.
Observed behavior
Midnight-crossing trips that arrive after the specified latestArrivalTime time are incorrectly included in search results. These trips appear with incorrect arrival times in the response, making them seem to arrive before the latestArrivalTime when they actually arrive after it.
Example
A trip scheduled to arrive at 03:39 CEST (01:39 UTC) appears as arriving at 01:46 CEST (23:46 UTC) and is included in results for an arriveBy search with latestArrivalTime 00:01 UTC, even though it actually arrives 1h 38min after the latestArrivalTime.
Version of OTP used (exact commit hash or JAR name)
2.9.0-SNAPSHOT commit 69dfcbe (dev-2.x)
Data sets in use (links to GTFS and OSM PBF files)
Skånetrafiken NeTEx data (ST_netex.zip) containing the following midnight-crossing ServiceJourney:
<ServiceJourney version="any" id="SE:276:ServiceJourney:1120000357544809">
<TransportMode>rail</TransportMode>
<dayTypes>
<DayTypeRef ref="SE:276:DayType:848"/>
</dayTypes>
<JourneyPatternRef ref="SE:276:JourneyPattern:1129420000114658" version="any"/>
<passingTimes>
<TimetabledPassingTime version="any" id="SE:276:TimetabledPassingTime:1120000357544795">
<StopPointInJourneyPatternRef ref="SE:276:StopPointInJourneyPattern:1129420000114658_1120000357543682" version="any"/>
<DepartureTime>02:35:00</DepartureTime>
<DepartureDayOffset>1</DepartureDayOffset>
</TimetabledPassingTime>
<!-- ... intermediate stops ... -->
<TimetabledPassingTime version="any" id="SE:276:TimetabledPassingTime:1120000357544805">
<StopPointInJourneyPatternRef ref="SE:276:StopPointInJourneyPattern:1129420000114658_1120000357543692" version="any"/>
<ArrivalTime>03:39:00</ArrivalTime>
<ArrivalDayOffset>1</ArrivalDayOffset>
</TimetabledPassingTime>
</passingTimes>
</ServiceJourney>
Note the DayOffset=1 indicating this is a midnight-crossing trip arriving at 03:39 on the day after the service date.
Command line used to start OTP
java -Xmx16G -Dlogging.level.org.opentripplanner.routing.algorithm.raptoradapter.router.TransitRouter=DEBUG -Dlogging.level.org.opentripplanner.ext.realtimeresolver.RealtimeResolver=DEBUG -Dlogging.level.org.opentripplanner.routing.algorithm.mapping.RoutingResponseMapper=DEBUG -jar otp-shaded/target/otp-shaded-2.9.0-SNAPSHOT.jar --load /Users/ivanaladjoff/dev/skane/otpbygg/default
Router config and graph build config JSON
Relevant router config:
{
"routingDefaults": {
"itineraryFilters": {
"filterItinerariesWithSameFirstOrLastTrip": false,
"groupSimilarityKeepOne": 0.99,
"transitGeneralizedCostLimit": {
"costLimitFunction": "900 + 1.5 x",
"intervalRelaxFactor": 0.4
}
},
"transferSlack": 180,
"accessEgress": {
"maxDuration": "PT50M"
}
},
"transit": {
"pagingSearchWindowAdjustments": [ "12h", "0h"],
"dynamicSearchWindow": {
"maxWindow": "PT24H"
}
},
"updaters": [
{
"type": "siri-azure-et-updater",
"customMidnight": "4",
"fuzzyTripMatching": false,
"feedId": "ST"
}
]
}
Note: customMidnight: 4 indicates service day changes at 04:00.
build-config.json:
{
"areaVisibility": true,
"platformEntriesLinking": true,
"dataImportReport": true,
"maxTransferDuration": "PT1504S",
"maxStopToShapeSnapDistance": 500,
"transitModelTimeZone": "Europe/Stockholm",
"transitServiceStart": "2023-11-01",
"transitServiceEnd": "2025-12-31",
"islandPruning": {
"islandWithoutStopsMaxSize": 5,
"islandWithStopsMaxSize": 2
},
"osmDefaults": {
"timeZone": "Europe/Stockholm",
"osmTagMapping": "norway"
},
"netexDefaults" : {
"feedId": "ST",
"sharedFilePattern" : "ST_stops.xml",
"sharedGroupFilePattern" : "(\\w{2})_shared_data.xml",
"groupFilePattern" : "(\\w{2})_line.*\\.xml",
"noTransfersOnIsolatedStops": true
},
"gtfsDefaults": {
"discardMinTransferTimes": true
},
"transitRouteToStationCentroid": [ ...
Steps to reproduce the problem
- Build a graph with GTFS data containing midnight-crossing trips (trips with times > 24:00:00)
- Execute the following GraphQL query:
{
trip(
from: { coordinates: { latitude: 55.609224, longitude: 13.000547 } }
to: { coordinates: { latitude: 55.708507, longitude: 13.191408 } }
dateTime: "2025-10-13T00:01:00Z"
arriveBy: true
numTripPatterns: 5
) {
tripPatterns {
legs {
mode
aimedEndTime
serviceDate
toPlace { name }
serviceJourney { id }
}
}
}
}
- Observe that ServiceJourney ST:SE:276:ServiceJourney:1120000357544809 is returned with:
- Displayed arrival time: 01:46 CEST (23:46 UTC) - appears before latestArrivalTime
- Actual arrival time at that stop: 03:39 CEST (01:39 UTC) - after latestArrivalTime - The trip should be excluded from results since it arrives at 01:39 UTC, which is after the 00:01 UTC latestArrivalTime specified in the query.
Note: The bug specifically affects arriveBy searches with midnight-crossing trips. Regular trips and departBy searches work correctly.