docs: public Iterable<StopTime> getInterpolatedStopTimesForTrip (String trip_id) throws FirstAndLastStopsDoNotHaveTimes {
          // clone stop times so as not to modify base GTFS structures
          StopTime[] stopTimes = StreamSupport.stream(getOrderedStopTimesForTrip(trip_id).spliterator(), false)
                  .map(st -> st.clone())
                  .toArray(i -> new StopTime[i]);
  
          // avoid having to make sure that the array has length below.
          if (stopTimes.length == 0) return Collections.emptyList();
  
          // first pass: set all partially filled stop times
          for (StopTime st : stopTimes) {
              if (st.arrival_time != Entity.INT_MISSING && st.departure_time == Entity.INT_MISSING) {
                  st.departure_time = st.arrival_time;
              }
  
              if (st.arrival_time == Entity.INT_MISSING && st.departure_time != Entity.INT_MISSING) {
                  st.arrival_time = st.departure_time;
              }
          }
  
          // quick check: ensure that first and last stops have times.
          // technically GTFS requires that both arrival_time and departure_time be filled at both the first and last stop,
          // but we are slightly more lenient and only insist that one of them be filled at both the first and last stop.
          // The meaning of the first stop's arrival time is unclear, and same for the last stop's departure time (except
          // in the case of interlining).
  
          // it's fine to just check departure time, as the above pass ensures that all stop times have either both
          // arrival and departure times, or neither
          if (stopTimes[0].departure_time == Entity.INT_MISSING || stopTimes[stopTimes.length - 1].departure_time == Entity.INT_MISSING) {
              throw new FirstAndLastStopsDoNotHaveTimes();
          }
  
          // second pass: fill complete stop times
          int startOfInterpolatedBlock = -1;
          for (int stopTime = 0; stopTime < stopTimes.length; stopTime++) {
  
              if (stopTimes[stopTime].departure_time == Entity.INT_MISSING && startOfInterpolatedBlock == -1) {
                  startOfInterpolatedBlock = stopTime;
              }
              else if (stopTimes[stopTime].departure_time != Entity.INT_MISSING && startOfInterpolatedBlock != -1) {
                  throw new RuntimeException("Missing stop times not supported.");
              }
          }
  
          return Arrays.asList(stopTimes);
      }