diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_position/RealtimeVehiclePatternMatcher.java b/application/src/main/java/org/opentripplanner/updater/vehicle_position/RealtimeVehiclePatternMatcher.java index 8e4a3ace823..832af758bb5 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_position/RealtimeVehiclePatternMatcher.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_position/RealtimeVehiclePatternMatcher.java @@ -18,7 +18,9 @@ import java.time.Duration; import java.time.Instant; import java.time.LocalDate; +import java.time.LocalTime; import java.time.ZoneId; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -36,6 +38,7 @@ import org.opentripplanner.street.geometry.WgsCoordinate; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.site.StopLocation; +import org.opentripplanner.transit.model.timetable.FrequencyEntry; import org.opentripplanner.transit.model.timetable.OccupancyStatus; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripTimes; @@ -382,10 +385,30 @@ private PatternAndRealtimeVehicle toRealtimeVehicle( throw UpdateException.of(scopedTripId, NO_SERVICE_ON_DATE); } + var scheduledTimetable = getStaticPattern.apply(trip).getScheduledTimetable(); // the trip times are only used for mapping the GTFS-RT stop_sequence back to a stop. // because new trips without trip times are created for realtime-updated ones, we explicitly // look at the static trips for the stop_sequence->stop mapping - var staticTripTimes = getStaticPattern.apply(trip).getScheduledTimetable().getTripTimes(trip); + var staticTripTimes = scheduledTimetable.getTripTimes(trip); + + if ( + !scheduledTimetable.getFrequencyEntries().isEmpty() && + vehiclePosition.getTrip().hasStartDate() + ) { + var updateStartTime = LocalTime.parse(vehiclePosition.getTrip().getStartTime()); + staticTripTimes = scheduledTimetable + .getFrequencyEntries() + .stream() + .map(FrequencyEntry::tripTimes) + .filter(e -> { + var start = e.getScheduledDepartureTime(0); + var startTime = LocalTime.ofSecondOfDay(start).truncatedTo(ChronoUnit.MINUTES); + return updateStartTime.equals(startTime); + }) + .findFirst() + .orElse(null); + } + if (staticTripTimes == null) { throw UpdateException.of(scopedTripId, TRIP_NOT_FOUND_IN_PATTERN); }