@Override
    public Optional<DateTime> calculateNextTime(DateTime previousExecutionTime, DateTime lastNextTime, JobSchedulerClock clock) {
        final Cron cron = CronUtils.getParser().parse(cronExpression());
        final ExecutionTime executionTime = ExecutionTime.forCron(cron);

        ZonedDateTime zdt = getZonedDateTime(lastNextTime == null ? clock.nowUTC() : lastNextTime);

        return executionTime
                .nextExecution(zdt)
                .map(this::toDateTime);
    }
@Test
    void testCalculateNextTime() {
        final long midnight01Jan2020Millis = 1577836800000L;
        final DateTime midnight01Jan2020 = new DateTime(midnight01Jan2020Millis, DateTimeZone.UTC);
        final JobSchedulerTestClock clock = new JobSchedulerTestClock(DateTime.now(DateTimeZone.UTC));
        // Every hour between 0800 and 1700.
        CronJobSchedule cronJobSchedule = CronJobSchedule.builder().cronExpression("0 0 8-17 1/1 * ? *").build();
        Optional<DateTime> next = cronJobSchedule.calculateNextTime(midnight01Jan2020.plusSeconds(30), midnight01Jan2020, clock);
        assertThat(next).isPresent();
        assertThat(next.get().getMillis()).isEqualTo(midnight01Jan2020Millis + (8 * 3600000));

        // 01 Jan 2020 is a Wednesday. Skip Wednesday and next execution should be 24 hours later.
        cronJobSchedule = CronJobSchedule.builder().cronExpression("0 0 * ? * MON,TUE,THU,FRI *").build();
        next = cronJobSchedule.calculateNextTime(midnight01Jan2020.plusSeconds(30), midnight01Jan2020, clock);
        assertThat(next).isPresent();
        assertThat(next.get().getMillis()).isEqualTo(midnight01Jan2020Millis + (24 * 3600000));
    }