StatisticsUtil { public static List<Instant> getBuckets(final Instant from, final Instant to, final DataResolution resolution, final ZoneId zoneId) { final List<Instant> result = new ArrayList<>(); LocalDateTime localStart = LocalDateTime.ofInstant(from, zoneId); final LocalDateTime localEnd = LocalDateTime.ofInstant(to, zoneId); while (!localStart.isAfter(localEnd)) { switch (resolution) { case MONTHLY: final Instant currentMonthStart = YearMonth.of(localStart.getYear(), localStart.getMonth()) .atDay(1).atStartOfDay().toInstant(ZoneOffset.UTC); result.add(Ordering.natural().max(from, currentMonthStart)); localStart = localStart.plusMonths(1).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0); break; case YEARLY: final Instant currentYearStart = YearMonth.of(localStart.getYear(), 1) .atDay(1).atStartOfDay().toInstant(ZoneOffset.UTC); result.add(Ordering.natural().max(from, currentYearStart)); localStart = localStart.plusYears(1).withMonth(1).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0); break; case DAILY: final Instant currentDayStart = localStart.withHour(0).withMinute(0).withSecond(0).withNano(0) .toInstant(ZoneOffset.UTC); result.add(Ordering.natural().max(from, currentDayStart)); localStart = localStart.plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0); break; case WEEKLY: final int daysOff = 1 - localStart.getDayOfWeek().getValue(); final Instant currentWeekStart = localStart.plusDays(daysOff).withHour(0).withMinute(0).withSecond(0) .withNano(0).toInstant(ZoneOffset.UTC); result.add(currentWeekStart); localStart = localStart.plusDays(7).plusDays(daysOff).withHour(0).withMinute(0).withSecond(0).withNano(0); break; case HOURLY: final Instant currentHourStart = ZonedDateTime.of(localStart.withMinute(0).withSecond(0).withNano(0), zoneId) .toInstant(); result.add(Ordering.natural().max(from, currentHourStart)); localStart = localStart.plusHours(1).withMinute(0).withSecond(0).withNano(0); break; default: } } return result; } private  StatisticsUtil(); static List<Instant> getBuckets(final Instant from, final Instant to, final DataResolution resolution, final ZoneId zoneId);  }
@Test public void testStartAfterEnd() { final Instant wrongFrom = Instant.parse("2019-04-01T00:00:00.000Z"); final Instant wrongTo = Instant.parse("2019-03-30T17:00:00.000Z"); Arrays.stream(DataResolution.values()).forEach(dr -> { assertTrue(StatisticsUtil.getBuckets(wrongFrom, wrongTo, dr, ZoneId.of("Z")).isEmpty()); }); }