ExtendedCalendarServiceImpl implements ExtendedCalendarService { @Override public List<Date> getNextServiceDatesForDepartureInterval( ServiceIdActivation serviceIds, ServiceInterval serviceInterval, long time) { List<Date> serviceDates = _serviceDatesByServiceIds.get(serviceIds); if (CollectionsLibrary.isEmpty(serviceDates)) return Collections.emptyList(); int offset = (serviceInterval.getMaxDeparture() - serviceInterval.getMinDeparture()) * 1000; Date offsetDate = new Date(time - offset); int startIndex = Collections.binarySearch(serviceDates, offsetDate); if (startIndex < 0) startIndex = -(startIndex + 1); startIndex = Math.max(0, startIndex - 1); List<Date> serviceDatesToReturn = new ArrayList<Date>(); boolean directHit = false; for (int index = startIndex; index < serviceDates.size(); index++) { Date serviceDate = serviceDates.get(index); long timeFrom = serviceDate.getTime() + serviceInterval.getMinDeparture() * 1000; long timeTo = serviceDate.getTime() + serviceInterval.getMaxDeparture() * 1000; if (time < timeFrom) { if (!directHit) { serviceDatesToReturn.add(serviceDate); } return serviceDatesToReturn; } if (timeFrom <= time && time <= timeTo) { serviceDatesToReturn.add(serviceDate); directHit = true; } } return serviceDatesToReturn; }  void setServiceDateLowerBoundsInWeeks(int serviceDateLowerBoundsInWeeks); void setServiceDateUpperBoundsInWeeks(int serviceDateUpperBoundsInWeeks); @Autowired void setCalendarService(CalendarService calendarService); @Autowired void setTransitGraphDao(TransitGraphDao transitGraphDao); void setServiceDateRangeCacheInterval(int hours); void setServiceDateRangeCache(Cache serviceDateRangeCache); @PostConstruct @Refreshable(dependsOn = RefreshableResources.CALENDAR_DATA) void start(); @Cacheable @Override Set<ServiceDate> getServiceDatesForServiceIds(
      ServiceIdActivation serviceIds); @Cacheable @Override Set<Date> getDatesForServiceIds(ServiceIdActivation serviceIds); @Cacheable List<Date> getDatesForServiceIdsAsOrderedList(
      ServiceIdActivation serviceIds); @SuppressWarnings("unchecked") @Override Collection<Date> getServiceDatesWithinRange(
      ServiceIdActivation serviceIds, ServiceInterval interval, Date from,
      Date to); @Override @Cacheable boolean areServiceIdsActiveOnServiceDate(
      ServiceIdActivation serviceIds, Date serviceDate); @Override List<Date> getServiceDatesForInterval(ServiceIdActivation serviceIds,
      ServiceInterval serviceInterval, long time, boolean findDepartures); @Override List<Date> getNextServiceDatesForDepartureInterval(
      ServiceIdActivation serviceIds, ServiceInterval serviceInterval, long time); @Override List<Date> getPreviousServiceDatesForArrivalInterval(
      ServiceIdActivation serviceIds, ServiceInterval serviceInterval, long time);  }
@Test public void testGetNextServiceDatesForDepartureInterval() { BlockEntry blockA = block("blockA"); blockConfiguration(blockA, serviceIds(lsids("sA"), lsids())); List<BlockEntry> blocks = Arrays.asList(blockA); Mockito.when(_transitGraphDao.getAllBlocks()).thenReturn(blocks); _service.start(); ServiceIdActivation serviceIds = serviceIds(lsids("sA"), lsids()); int inFrom = time(8, 00); int inTo = time(20, 00); ServiceInterval interval = new ServiceInterval(inFrom, inFrom, inTo, inTo); long time = dateAsLong("2010-09-10 09:30"); List<Date> dates = _service.getNextServiceDatesForDepartureInterval( serviceIds, interval, time); assertEquals(1, dates.size()); assertEquals(date("2010-09-10 00:00"), dates.get(0)); time = dateAsLong("2010-09-10 21:30"); dates = _service.getNextServiceDatesForDepartureInterval(serviceIds, interval, time); assertEquals(1, dates.size()); assertEquals(date("2010-09-11 00:00"), dates.get(0)); time = dateAsLong("2010-09-11 21:30"); dates = _service.getNextServiceDatesForDepartureInterval(serviceIds, interval, time); assertEquals(0, dates.size()); }