TimeUtil { public static Instant nextInstant(Instant instant, Schedule schedule) { final ExecutionTime executionTime = ExecutionTime.forCron(cron(schedule)); final ZonedDateTime utcDateTime = instant.atZone(UTC); return executionTime.nextExecution(utcDateTime) .orElseThrow(IllegalArgumentException::new) .toInstant(); } private  TimeUtil(); static Instant lastInstant(Instant instant, Schedule schedule); static Instant previousInstant(Instant instant, Schedule schedule); static Instant nextInstant(Instant instant, Schedule schedule); static List<Instant> instantsInRange(Instant firstInstant, Instant lastInstant,
                                              Schedule schedule); static List<Instant> instantsInReversedRange(Instant firstInstant, Instant lastInstant,
                                                      Schedule schedule); static boolean isAligned(Instant instant, Schedule schedule); static ZonedDateTime addOffset(ZonedDateTime time, String offset); static ZonedDateTime subtractOffset(ZonedDateTime time, String offset); static Cron cron(Schedule schedule); static Instant offsetInstant(Instant origin, Schedule schedule, int offset);  }
@Test public void shouldGetNextInstant() { final Instant nextTimeHours = parse("2016-01-19T10:00:00.00Z"); final Instant nextTimeDays = parse("2016-01-20T00:00:00.00Z"); final Instant nextTimeWeeks = parse("2016-01-25T00:00:00.00Z"); final Instant nextTimeMonths = parse("2016-02-01T00:00:00.00Z"); final Instant hour = nextInstant(TIME, Schedule.HOURS); assertThat(hour, is(nextTimeHours)); final Instant day = nextInstant(TIME, Schedule.DAYS); assertThat(day, is(nextTimeDays)); final Instant weeks = nextInstant(TIME, Schedule.WEEKS); assertThat(weeks, is(nextTimeWeeks)); final Instant months = nextInstant(TIME, Schedule.MONTHS); assertThat(months, is(nextTimeMonths)); }