cron-utils icon indicating copy to clipboard operation
cron-utils copied to clipboard

[potential bug] ExecutionTime.nextExecution returns Empty When time is beyond 2099 years

Open Chazzzzzzz opened this issue 3 years ago • 0 comments
trafficstars

Hey guys, we find an issue in latest cron-utils release: ExecutionTime.nextExecution will return Empty when time is beyond 2099 years. The following is my test code

In the test class, I use 12/31/2099 as the current time and try to find next execution time after one month. The result I get is empty. Please check and let me know if I am doing a wrong way or its a bug of the library.

class app `

import static com.cronutils.model.CronType.QUARTZ; import static com.cronutils.model.definition.CronDefinitionBuilder.instanceDefinitionFor;

import java.time.ZonedDateTime; import java.util.Optional;

import com.cronutils.model.Cron; import com.cronutils.model.time.ExecutionTime; import com.cronutils.parser.CronParser;

public class app { private static final String CRON_START = "cron("; private static final int CRON_OFFSET = CRON_START.length(); private static final CronParser CRON_PARSER = new CronParser(instanceDefinitionFor(QUARTZ));

private static Cron getCronExpression(String scheduleExpression, String scheduleName) throws Exception {
    // This method will parse cron("EXPRESSION") and return quartz cron.
    StringBuilder cronExpression = new StringBuilder();

    // Adding 0 because Quartz supports seconds fields.
    cronExpression.append("0 ");
    cronExpression.append(scheduleExpression.substring(CRON_OFFSET, scheduleExpression.length() - 1));
    try {
        Cron quartzExpression =  CRON_PARSER.parse(cronExpression.toString());
        quartzExpression.validate();
        return quartzExpression;
    }
    catch (Exception e) {
        throw e;
    }
}

public static Optional<ZonedDateTime> getNextNthExecutionTime(int n, ZonedDateTime startTime,
    String scheduleExpression, String scheduleName) throws Exception {
    Cron cronExpression = getCronExpression(scheduleExpression, scheduleName);

    ExecutionTime executionTime = ExecutionTime.forCron(cronExpression);

    Optional<ZonedDateTime> nextRun = Optional.of(startTime);
    for (int i=0; i<n; i++) {
        nextRun = executionTime.nextExecution(nextRun.get());
        if (!nextRun.isPresent()) {
            throw new RuntimeException("failed");
        }
    }

    return nextRun;
}

} `

test class `

import static org.junit.Assert.assertEquals;

import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Optional;

import org.junit.Test;

public class test_app {

@Test
public void test() throws Exception {
    ZonedDateTime currentRun = ZonedDateTime.of(2099,12,31,9,
        0,0,0, ZoneId.of("America/Los_Angeles"));
    Optional<ZonedDateTime> targetRun = app.getNextNthExecutionTime(1, currentRun,
        "cron(0 9 L 1/2 ? *)", "Sched1");
    ZonedDateTime expectedRun = ZonedDateTime.of(2100,2,29,9,
        0,0,0, ZoneId.of("America/Los_Angeles"));
    assertEquals("Next Nth execution date doesn't match", expectedRun, targetRun.get());
}

} `

Chazzzzzzz avatar Sep 06 '22 21:09 Chazzzzzzz