src/main/java/com/conveyal/gtfs/stats/StopStats.java
public int getStopHeadwayForTrips (String stop_id, List<Trip> trips, LocalTime from, LocalTime to) {
        TIntList timesAtStop = new TIntArrayList();
        Set<String> tripIds = trips.stream()
                .map(t -> t.trip_id)
                .collect(Collectors.toSet());

        List<StopTime> stopTimes = feed.getStopTimesForStop(stop_id).stream()
                .filter(st -> tripIds.contains(st.trip_id))
                .collect(Collectors.toList());

        for (StopTime st : stopTimes) {

            // these trips are actually running on the next day, skip them
            if (st.departure_time > 86399 || st.departure_time < 0) continue;

            LocalTime timeAtStop = LocalTime.ofSecondOfDay(st.departure_time);

            if (timeAtStop.isAfter(to) || timeAtStop.isBefore(from)) {
                continue;
            }

            timesAtStop.add(st.departure_time);
        }
        timesAtStop.sort();

        // convert to deltas
        TIntList deltas = new TIntArrayList();

        for (int i = 0; i < timesAtStop.size() - 1; i++) {
            int delta = timesAtStop.get(i + 1) - timesAtStop.get(i);

            if (delta > 60) deltas.add(delta);
        }

        if (deltas.isEmpty()) return -1;

        return deltas.sum() / deltas.size();
    }
public int getStopHeadwayForTrips (String stop_id, List<Trip> trips, LocalTime from, LocalTime to) {
        TIntList timesAtStop = new TIntArrayList();
        Set<String> tripIds = trips.stream()
                .map(t -> t.trip_id)
                .collect(Collectors.toSet());

        List<StopTime> stopTimes = feed.getStopTimesForStop(stop_id).stream()
                .filter(st -> tripIds.contains(st.trip_id))
                .collect(Collectors.toList());

        for (StopTime st : stopTimes) {

            // these trips are actually running on the next day, skip them
            if (st.departure_time > 86399 || st.departure_time < 0) continue;

            LocalTime timeAtStop = LocalTime.ofSecondOfDay(st.departure_time);

            if (timeAtStop.isAfter(to) || timeAtStop.isBefore(from)) {
                continue;
            }

            timesAtStop.add(st.departure_time);
        }
        timesAtStop.sort();

        // convert to deltas
        TIntList deltas = new TIntArrayList();

        for (int i = 0; i < timesAtStop.size() - 1; i++) {
            int delta = timesAtStop.get(i + 1) - timesAtStop.get(i);

            if (delta > 60) deltas.add(delta);
        }

        if (deltas.isEmpty()) return -1;

        return deltas.sum() / deltas.size();
    }
TODO: specified stop vs. first stop