Code Monkey home page Code Monkey logo

cron-utils's People

Contributors

albertotn avatar albuhuba avatar alenkacz avatar curioustechizen avatar dependabot[bot] avatar emsyzz avatar eyal-shalev avatar haarolean avatar indeedsi avatar j0b10 avatar jgoldhammer avatar jmrozanec avatar jpotts2 avatar kensipe avatar kostapc avatar lodenrogue avatar lpbak avatar maxmorozov avatar mccartney avatar meincs avatar minidmnv avatar mureinik avatar nielsdoucet avatar pangyikhei avatar pkoenig10 avatar primael avatar rhanton avatar skyline75489 avatar svenssonweb avatar thachhoang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cron-utils's Issues

BetweenDayOfWeekValueGenerator does not work for the first day of a month in some cases.

With this CronDefinition:

CronDefinitionBuilder.defineCron()
            .withMinutes().and()
            .withHours().and()
            .withDayOfMonth()
                .supportsL().supportsW()
                .and()
            .withMonth().and()
            .withDayOfWeek()
                .withMondayDoWValue(1)
                .withValidRange(1, 7)
                .supportsHash().supportsL()
                .and()
            .withYear().and()
                .lastFieldOptional()

and this cron expression:
"30 3 * * MON-FRI"

executionTime.nextExecution(1970-01-01....) returns 1970-01-02... instead of 1970-01-01. It seems to always do this on when the first day of the month falls within the DoW range. It looks like an initial case type bug. The BetweenDayOfWeekValueGenerator will never return the value 1 in this case - only the value 8.

The result is that if I execute this over the year of 1970, I'd expect to get 261 days. Instead I get 245 days.

Based on this bug for the year 1970, I'd expect to lose 8 days. I'm losing 16 days though. Taking a quick look at the output, it appears the same issue exists for the last day of the month when the last day falls within the DoW range. For example, cron-utils will not return 1970-07-31 (a Friday) for the above cron expression.

every 2 min schedule doesn't roll over to next hour

Sorry for scala, but it should be pretty clear:

object CronError extends App {
  val cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX)
  val cron = new CronParser(CronSchedule.cronDefinition).parse("0 */2 * * * *")
  val executionTime = ExecutionTime.forCron(cron)
  val time = DateTime.parse("2015-09-05T13:56:00.000-07:00")
  val next = executionTime.nextExecution(time)
  val shouldBeInNextHour = executionTime.nextExecution(next)
  val text = CronDescriptor.instance(Locale.US).describe(cron)
  println(s"Schedule: $text")
  println(s"Original time: $time")
  println(s"Next event time: $next")
  println(s"It should be in next hour: $shouldBeInNextHour")
}

Library version: 3.1.0

PS. at the same time pattern "0 */1 * * * *" works fine.

Buggy or wrong Cron4j Definition? Impossible to set an "Every X times" crons.

Hello, if I'm not wrong the Cron4j definition is wrong for "Every X times" crons.

In Cron4J Manual (http://goo.gl/2CgX2h) to have a task execute every 5 minutes you use:
***/5 * * * ***
And to have the task execute at XX:05 you use:
**5 * * * ***

Now there seems to be some special case in between which Cron4J supports but its not documented anywhere nor I found it in the manuals and examples of Cron4J and its this one:
**/5 * * * ***

_BUG:_
Cron-Utils interprets "/5 * * * *" as "Every 5 minutes" but in Cron4J it is being interpreted as "once a hour at 05min".

Now this gets even worse with the Cron-Utils mapper. As it maps any "/x" and "/x" to "/x". So even if you map from CRON4J to CRON4J it breaks each cron string removing the "" having a unexpected result.

Here is a demo code:

    public static void main(String[] args) {

        // Cron Definitions & Parsers
        CronDefinition unixCronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX);
        CronDefinition cron4jCronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.CRON4J);
        CronParser unixParser = new CronParser(unixCronDefinition);
        CronParser cron4jParser = new CronParser(unixCronDefinition);

        // From UNIX to CRON4J Mapper
        CronMapper cronMapper = new CronMapper(unixCronDefinition, cron4jCronDefinition);

        // ISSUE 1: Every X times BUG for CRON4J
        System.out.println(cronMapper.map(unixParser.parse("*/5 * * * *")).asString()); // WRONG - /5 * * * * (Should be */5 * * * *)
        System.out.println(cronMapper.map(unixParser.parse("/5 * * * *")).asString()); // WRONG - /5 * * * * (Should be */5 * * * *)
        System.out.println(cronMapper.map(unixParser.parse("5 * * * *")).asString()); // OK - 5 * * * *

        // Descriptor 
        CronDescriptor descriptor = CronDescriptor.instance(Locale.UK);
        System.out.println(descriptor.describe(cron4jParser.parse("*/5 * * * *"))); // OK - every 5 minutes
        System.out.println(descriptor.describe(cron4jParser.parse("/5 * * * *")));  // WRONG - every 5 minutes (Should be "every hour at minute 5")
        System.out.println(descriptor.describe(cron4jParser.parse("5 * * * *")));   // OK - every hour at minute 5

        // ISSUE 2: (Not so important)
        // This is not supported by Cron-Utils
        // In Cron4J Manual http://www.sauronsoftware.it/projects/cron4j/manual.php
        System.out.println(descriptor.describe(cron4jParser.parse("0 5 * * *|8 10 * * *|22 17 * * *")));
        System.out.println(cronMapper.map(unixParser.parse("0 5 * * *|8 10 * * *|22 17 * * *")).asString()); 

    }

Basically the only thing missing here is that Cron-Utils shouls add a "/x" to the evey x times definition. And to parse "/x" the same as "x" and not as "/x".

Thanks for the awesome work done so far. Cron-Utils is just awesome useful.

JodaTime throws exception on hour shifting

This code:

CronDefinition definition = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
CronParser parser = new CronParser(definition);
Cron cron = parser.parse("0/1 * * 1/1 * ? *");  // Every 1 second
ExecutionTime executionTime = ExecutionTime.forCron(cron);

DateTime now = new DateTime().withTime(23, 59, 59, 0);
DateTime nextExecution = executionTime.nextExecution(now);

Would throw this exception: org.joda.time.IllegalFieldValueException: Value 24 for hourOfDay must be in the range [0,23] because 23:59:59 + 1 second would become 24:00:00, which is an invalid hour for a new DateTime object.

nextExecution not working for '0/30 * * * * *'

For the cron expression 0/30 * * * * *, with a custom definition of:

// Unix Crontab with seconds allowed
CronDefinition cronDefinition = CronDefinitionBuilder.defineCron()
.withSeconds().and()
.withMinutes().and()
.withHours().and()
.withDayOfMonth().and()
.withMonth().and()
.withDayOfWeek().withValidRange(0, 7).withMondayDoWValue(1).withIntMapping(7, 0).and()
.instance();

Performing a nextExecution call when the input DateTime value is between 30 and 59 seconds of the minute causes the method to return with a DateTime at the previous minute instead of the next minute.

For example:

nextExecution('2015-08-28 12:05:44') -> 2015-08-28 12:05:00
nextExecution('2015-08-28 12:05:14') -> 2015-08-28 12:05:30

Note that I've also tried this with '*/30 * * * * *' and got the same results.

Unit tests:

@Test
public void testCronExpressionAfterHalf() {

    CronDefinition cronDefinition = CronDefinitionBuilder.defineCron()
            .withSeconds().and()
            .withMinutes().and()
            .withHours().and()
            .withDayOfMonth().and()
            .withMonth().and()
            .withDayOfWeek().withValidRange(0, 7).withMondayDoWValue(1).withIntMapping(7, 0).and()
            .instance();

    CronParser parser = new CronParser(cronDefinition);
    Cron cron = parser.parse("*/30 * * * * *");

    MutableDateTime mutableDateTime = new MutableDateTime();
    mutableDateTime.setDateTime(2015, 8, 28, 12, 5, 44, 0);

    DateTime startDateTime = mutableDateTime.toDateTime();

    mutableDateTime = new MutableDateTime();
    mutableDateTime.setDateTime(2015, 8, 28, 12, 6, 0, 0);

    DateTime expectedDateTime = mutableDateTime.toDateTime();

    ExecutionTime executionTime = ExecutionTime.forCron(cron);

    DateTime nextExecutionDateTime = executionTime.nextExecution(startDateTime);
    MatcherAssert.assertThat(nextExecutionDateTime, Matchers.equalTo(expectedDateTime));
}

@Test
public void testCronExpressionBeforeHalf() {

    CronDefinition cronDefinition = CronDefinitionBuilder.defineCron()
            .withSeconds().and()
            .withMinutes().and()
            .withHours().and()
            .withDayOfMonth().and()
            .withMonth().and()
            .withDayOfWeek().withValidRange(0, 7).withMondayDoWValue(1).withIntMapping(7, 0).and()
            .instance();

    CronParser parser = new CronParser(cronDefinition);
    Cron cron = parser.parse("0/30 * * * * *");

    MutableDateTime mutableDateTime = new MutableDateTime();
    mutableDateTime.setDateTime(2015, 8, 28, 12, 5, 14, 0);

    DateTime startDateTime = mutableDateTime.toDateTime();

    mutableDateTime = new MutableDateTime();
    mutableDateTime.setDateTime(2015, 8, 28, 12, 5, 30, 0);

    DateTime expectedDateTime = mutableDateTime.toDateTime();

    ExecutionTime executionTime = ExecutionTime.forCron(cron);

    DateTime nextExecutionDateTime = executionTime.nextExecution(startDateTime);
    MatcherAssert.assertThat(nextExecutionDateTime, Matchers.equalTo(expectedDateTime));
}

Typo in README.md

Hello,

I just started using your library and noticed a typo in the README.md file.

On line:

//Get date for next execution
DateTime nextExecution = executionTime.timeToNextExecution(now));

Should be:

//Get date for next execution
DateTime nextExecution = executionTime.nextExecution(now));

Hope it helps.

UNIX Cron to QUARTZ expressions incorrect

Quartz does not support specifying both a day-of-week and a day-of-month value (you must currently use the '?' character in one of these fields).

For example: 0 0 0 * * 1 * is not legal in quartz, instead it must be: 0 0 0 ? * 1 *

Code such as:

        CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX);
        CronDefinition quartzDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
        CronMapper cronMapper = new CronMapper(cronDefinition, quartzDefinition);
        CronParser cronParser = new CronParser(cronDefinition);
        Cron cronCron = cronParser.parse(cronString);
        Cron quartzCron = cronMapper.map(cronCron);
        String result = quartzCron.asString();

Will take 0 0/2 * * * and produce 0 /2 * * * * - it should be 0 /2 * * ? * (or possibly 0 /2 ? * * *)

Using quartz 2.2.2 and cron-utils 3.1.2

cron mapping not working accurately where '?' symbol is supported.

I'm trying to translate a UNIX cron expression to Quartz cron expression. This is how I'm trying to do so (Groovy code):

Cron unixCron = new CronParser(new CronDefinitionBuilder().instanceDefinitionFor(CronType.UNIX)).parse('* * * * *')
CronMapper cronMapper = new CronMapper(CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX), CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ))
Cron quartzCron = cronMapper.map(unixCron)
String quartzCronExpression = quartzCron.asString()

However, * * * * * gets translated to 0 * * * * * * which is not valid (I think it should be 0 * * * * * ?). Is this a bug (or unsupported feature) or is my translation code wrong?

Thanks for your help.

Unix crontab nextExecution bug

I'm trying a simple unix crontab "* * * * 1", which should run every minute of every hour Mondays in every month, but nextExecution doesn't seem give the correct result. Following is the code:

    crontab = "* * * * 1";
    CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX);
    CronParser parser = new CronParser(cronDefinition);
    Cron cron = parser.parse(crontab);
    DateTime date = DateTime.now();
    System.out.println("now:" + date);
    ExecutionTime executionTime = ExecutionTime.forCron(cron);
    DateTime nextExecution = executionTime.nextExecution(date);
    DateTime lastExecution = executionTime.lastExecution(date);
    System.out.println("next execution:" + nextExecution);
    System.out.println("last execution:" + lastExecution);

Output:
now:2015-10-13T17:26:54.468-07:00
next execution:2015-11-02T00:00:00.000-08:00
last execution:2015-10-05T23:59:00.000-07:00

The last execution time seems correct, but next execution time should be 2015-10-19T00:00:00.000-07:00. It skips two weeks and also change the time zone. Can you guys take a look at it?

Thanks,
Jun

Getting extra execution times after updating to v3.1.2

Test File : https://gist.github.com/rtennantventuretech/3e201c854b3546bed2e7

v3.1.1

Test output

TEST1 - expecting 0 instants
instants.size() == 0
instants: []

TEST2 - expecting 12 instants
instants.size() == 12
instants: [1970-01-31T18:00:00.000Z, 1970-02-28T18:00:00.000Z, 1970-03-31T18:00:00.000Z, 1970-04-30T17:00:00.000Z, 1970-05-31T17:00:00.000Z, 1970-06-30T17:00:00.000Z, 1970-07-31T17:00:00.000Z, 1970-08-31T17:00:00.000Z, 1970-09-30T17:00:00.000Z, 1970-10-31T18:00:00.000Z, 1970-11-30T18:00:00.000Z, 1970-12-31T18:00:00.000Z]

v3.1.2

TEST1 - expecting 0 instants
instants.size() == 1
instants: [1970-01-02T06:00:00.000Z]
java.lang.AssertionError: expected [0] but found [1]
Expected :0
Actual   :1


TEST2 - expecting 12 instants
Uh Oh! Next == Previous
instants.size() == 298
instants: [1970-01-01T18:00:00.000Z, 1970-01-02T18:00:00.000Z, 1970-01-03T18:00:00.000Z, 1970-01-04T18:00:00.000Z, 1970-01-05T18:00:00.000Z, 1970-01-06T18:00:00.000Z, 1970-01-07T18:00:00.000Z, 1970-01-08T18:00:00.000Z, 1970-01-09T18:00:00.000Z, 1970-01-10T18:00:00.000Z, 1970-01-11T18:00:00.000Z, 1970-01-12T18:00:00.000Z, 1970-01-13T18:00:00.000Z, 1970-01-14T18:00:00.000Z, 1970-01-15T18:00:00.000Z, 1970-01-16T18:00:00.000Z, 1970-01-17T18:00:00.000Z, 1970-01-18T18:00:00.000Z, 1970-01-19T18:00:00.000Z, 1970-01-20T18:00:00.000Z, 1970-01-21T18:00:00.000Z, 1970-01-22T18:00:00.000Z, 1970-01-23T18:00:00.000Z, 1970-01-24T18:00:00.000Z, 1970-01-25T18:00:00.000Z, 1970-01-26T18:00:00.000Z, 1970-01-27T18:00:00.000Z, 1970-01-28T18:00:00.000Z, 1970-01-29T18:00:00.000Z, 1970-01-30T18:00:00.000Z, 1970-01-31T18:00:00.000Z, 1970-02-01T18:00:00.000Z, 1970-02-02T18:00:00.000Z, 1970-02-03T18:00:00.000Z, 1970-02-04T18:00:00.000Z, 1970-02-05T18:00:00.000Z, 1970-02-06T18:00:00.000Z, 1970-02-07T18:00:00.000Z, 1970-02-08T18:00:00.000Z, 1970-02-09T18:00:00.000Z, 1970-02-10T18:00:00.000Z, 1970-02-11T18:00:00.000Z, 1970-02-12T18:00:00.000Z, 1970-02-13T18:00:00.000Z, 1970-02-14T18:00:00.000Z, 1970-02-15T18:00:00.000Z, 1970-02-16T18:00:00.000Z, 1970-02-17T18:00:00.000Z, 1970-02-18T18:00:00.000Z, 1970-02-19T18:00:00.000Z, 1970-02-20T18:00:00.000Z, 1970-02-21T18:00:00.000Z, 1970-02-22T18:00:00.000Z, 1970-02-23T18:00:00.000Z, 1970-02-24T18:00:00.000Z, 1970-02-25T18:00:00.000Z, 1970-02-26T18:00:00.000Z, 1970-02-27T18:00:00.000Z, 1970-02-28T18:00:00.000Z, 1970-03-01T18:00:00.000Z, 1970-03-02T18:00:00.000Z, 1970-03-03T18:00:00.000Z, 1970-03-04T18:00:00.000Z, 1970-03-05T18:00:00.000Z, 1970-03-06T18:00:00.000Z, 1970-03-07T18:00:00.000Z, 1970-03-08T18:00:00.000Z, 1970-03-09T18:00:00.000Z, 1970-03-10T18:00:00.000Z, 1970-03-11T18:00:00.000Z, 1970-03-12T18:00:00.000Z, 1970-03-13T18:00:00.000Z, 1970-03-14T18:00:00.000Z, 1970-03-15T18:00:00.000Z, 1970-03-16T18:00:00.000Z, 1970-03-17T18:00:00.000Z, 1970-03-18T18:00:00.000Z, 1970-03-19T18:00:00.000Z, 1970-03-20T18:00:00.000Z, 1970-03-21T18:00:00.000Z, 1970-03-22T18:00:00.000Z, 1970-03-23T18:00:00.000Z, 1970-03-24T18:00:00.000Z, 1970-03-25T18:00:00.000Z, 1970-03-26T18:00:00.000Z, 1970-03-27T18:00:00.000Z, 1970-03-28T18:00:00.000Z, 1970-03-29T18:00:00.000Z, 1970-03-30T18:00:00.000Z, 1970-03-31T18:00:00.000Z, 1970-04-01T18:00:00.000Z, 1970-04-02T18:00:00.000Z, 1970-04-03T18:00:00.000Z, 1970-04-04T18:00:00.000Z, 1970-04-05T18:00:00.000Z, 1970-04-06T18:00:00.000Z, 1970-04-07T18:00:00.000Z, 1970-04-08T18:00:00.000Z, 1970-04-09T18:00:00.000Z, 1970-04-10T18:00:00.000Z, 1970-04-11T18:00:00.000Z, 1970-04-12T18:00:00.000Z, 1970-04-13T18:00:00.000Z, 1970-04-14T18:00:00.000Z, 1970-04-15T18:00:00.000Z, 1970-04-16T18:00:00.000Z, 1970-04-17T18:00:00.000Z, 1970-04-18T18:00:00.000Z, 1970-04-19T18:00:00.000Z, 1970-04-20T18:00:00.000Z, 1970-04-21T18:00:00.000Z, 1970-04-22T18:00:00.000Z, 1970-04-23T18:00:00.000Z, 1970-04-24T18:00:00.000Z, 1970-04-25T18:00:00.000Z, 1970-04-26T18:00:00.000Z, 1970-04-27T17:00:00.000Z, 1970-04-28T17:00:00.000Z, 1970-04-29T17:00:00.000Z, 1970-04-30T17:00:00.000Z, 1970-05-01T17:00:00.000Z, 1970-05-02T17:00:00.000Z, 1970-05-03T17:00:00.000Z, 1970-05-04T17:00:00.000Z, 1970-05-05T17:00:00.000Z, 1970-05-06T17:00:00.000Z, 1970-05-07T17:00:00.000Z, 1970-05-08T17:00:00.000Z, 1970-05-09T17:00:00.000Z, 1970-05-10T17:00:00.000Z, 1970-05-11T17:00:00.000Z, 1970-05-12T17:00:00.000Z, 1970-05-13T17:00:00.000Z, 1970-05-14T17:00:00.000Z, 1970-05-15T17:00:00.000Z, 1970-05-16T17:00:00.000Z, 1970-05-17T17:00:00.000Z, 1970-05-18T17:00:00.000Z, 1970-05-19T17:00:00.000Z, 1970-05-20T17:00:00.000Z, 1970-05-21T17:00:00.000Z, 1970-05-22T17:00:00.000Z, 1970-05-23T17:00:00.000Z, 1970-05-24T17:00:00.000Z, 1970-05-25T17:00:00.000Z, 1970-05-26T17:00:00.000Z, 1970-05-27T17:00:00.000Z, 1970-05-28T17:00:00.000Z, 1970-05-29T17:00:00.000Z, 1970-05-30T17:00:00.000Z, 1970-05-31T17:00:00.000Z, 1970-06-01T17:00:00.000Z, 1970-06-02T17:00:00.000Z, 1970-06-03T17:00:00.000Z, 1970-06-04T17:00:00.000Z, 1970-06-05T17:00:00.000Z, 1970-06-06T17:00:00.000Z, 1970-06-07T17:00:00.000Z, 1970-06-08T17:00:00.000Z, 1970-06-09T17:00:00.000Z, 1970-06-10T17:00:00.000Z, 1970-06-11T17:00:00.000Z, 1970-06-12T17:00:00.000Z, 1970-06-13T17:00:00.000Z, 1970-06-14T17:00:00.000Z, 1970-06-15T17:00:00.000Z, 1970-06-16T17:00:00.000Z, 1970-06-17T17:00:00.000Z, 1970-06-18T17:00:00.000Z, 1970-06-19T17:00:00.000Z, 1970-06-20T17:00:00.000Z, 1970-06-21T17:00:00.000Z, 1970-06-22T17:00:00.000Z, 1970-06-23T17:00:00.000Z, 1970-06-24T17:00:00.000Z, 1970-06-25T17:00:00.000Z, 1970-06-26T17:00:00.000Z, 1970-06-27T17:00:00.000Z, 1970-06-28T17:00:00.000Z, 1970-06-29T17:00:00.000Z, 1970-06-30T17:00:00.000Z, 1970-07-01T17:00:00.000Z, 1970-07-02T17:00:00.000Z, 1970-07-03T17:00:00.000Z, 1970-07-04T17:00:00.000Z, 1970-07-05T17:00:00.000Z, 1970-07-06T17:00:00.000Z, 1970-07-07T17:00:00.000Z, 1970-07-08T17:00:00.000Z, 1970-07-09T17:00:00.000Z, 1970-07-10T17:00:00.000Z, 1970-07-11T17:00:00.000Z, 1970-07-12T17:00:00.000Z, 1970-07-13T17:00:00.000Z, 1970-07-14T17:00:00.000Z, 1970-07-15T17:00:00.000Z, 1970-07-16T17:00:00.000Z, 1970-07-17T17:00:00.000Z, 1970-07-18T17:00:00.000Z, 1970-07-19T17:00:00.000Z, 1970-07-20T17:00:00.000Z, 1970-07-21T17:00:00.000Z, 1970-07-22T17:00:00.000Z, 1970-07-23T17:00:00.000Z, 1970-07-24T17:00:00.000Z, 1970-07-25T17:00:00.000Z, 1970-07-26T17:00:00.000Z, 1970-07-27T17:00:00.000Z, 1970-07-28T17:00:00.000Z, 1970-07-29T17:00:00.000Z, 1970-07-30T17:00:00.000Z, 1970-07-31T17:00:00.000Z, 1970-08-01T17:00:00.000Z, 1970-08-02T17:00:00.000Z, 1970-08-03T17:00:00.000Z, 1970-08-04T17:00:00.000Z, 1970-08-05T17:00:00.000Z, 1970-08-06T17:00:00.000Z, 1970-08-07T17:00:00.000Z, 1970-08-08T17:00:00.000Z, 1970-08-09T17:00:00.000Z, 1970-08-10T17:00:00.000Z, 1970-08-11T17:00:00.000Z, 1970-08-12T17:00:00.000Z, 1970-08-13T17:00:00.000Z, 1970-08-14T17:00:00.000Z, 1970-08-15T17:00:00.000Z, 1970-08-16T17:00:00.000Z, 1970-08-17T17:00:00.000Z, 1970-08-18T17:00:00.000Z, 1970-08-19T17:00:00.000Z, 1970-08-20T17:00:00.000Z, 1970-08-21T17:00:00.000Z, 1970-08-22T17:00:00.000Z, 1970-08-23T17:00:00.000Z, 1970-08-24T17:00:00.000Z, 1970-08-25T17:00:00.000Z, 1970-08-26T17:00:00.000Z, 1970-08-27T17:00:00.000Z, 1970-08-28T17:00:00.000Z, 1970-08-29T17:00:00.000Z, 1970-08-30T17:00:00.000Z, 1970-08-31T17:00:00.000Z, 1970-09-01T17:00:00.000Z, 1970-09-02T17:00:00.000Z, 1970-09-03T17:00:00.000Z, 1970-09-04T17:00:00.000Z, 1970-09-05T17:00:00.000Z, 1970-09-06T17:00:00.000Z, 1970-09-07T17:00:00.000Z, 1970-09-08T17:00:00.000Z, 1970-09-09T17:00:00.000Z, 1970-09-10T17:00:00.000Z, 1970-09-11T17:00:00.000Z, 1970-09-12T17:00:00.000Z, 1970-09-13T17:00:00.000Z, 1970-09-14T17:00:00.000Z, 1970-09-15T17:00:00.000Z, 1970-09-16T17:00:00.000Z, 1970-09-17T17:00:00.000Z, 1970-09-18T17:00:00.000Z, 1970-09-19T17:00:00.000Z, 1970-09-20T17:00:00.000Z, 1970-09-21T17:00:00.000Z, 1970-09-22T17:00:00.000Z, 1970-09-23T17:00:00.000Z, 1970-09-24T17:00:00.000Z, 1970-09-25T17:00:00.000Z, 1970-09-26T17:00:00.000Z, 1970-09-27T17:00:00.000Z, 1970-09-28T17:00:00.000Z, 1970-09-29T17:00:00.000Z, 1970-09-30T17:00:00.000Z, 1970-10-01T17:00:00.000Z, 1970-10-02T17:00:00.000Z, 1970-10-03T17:00:00.000Z, 1970-10-04T17:00:00.000Z, 1970-10-05T17:00:00.000Z, 1970-10-06T17:00:00.000Z, 1970-10-07T17:00:00.000Z, 1970-10-08T17:00:00.000Z, 1970-10-09T17:00:00.000Z, 1970-10-10T17:00:00.000Z, 1970-10-11T17:00:00.000Z, 1970-10-12T17:00:00.000Z, 1970-10-13T17:00:00.000Z, 1970-10-14T17:00:00.000Z, 1970-10-15T17:00:00.000Z, 1970-10-16T17:00:00.000Z, 1970-10-17T17:00:00.000Z, 1970-10-18T17:00:00.000Z, 1970-10-19T17:00:00.000Z, 1970-10-20T17:00:00.000Z, 1970-10-21T17:00:00.000Z, 1970-10-22T17:00:00.000Z, 1970-10-23T17:00:00.000Z, 1970-10-24T17:00:00.000Z, 1970-10-25T17:00:00.000Z]
java.lang.AssertionError: expected [12] but found [298]
Expected :12
Actual   :298

Valid quartz range expression is considered invalid. Range validations should be contextual to cron definition.

Version 3.1.0
Quartz parser fails for day-of-week range of SUN-SAT. The Quartz definition appears correct but when the Quartz-based parser is created, the "DAY_OF_WEEK" constraints.stringMapping values are incorrect. MON = 1 even though mondayDoWValue = 2.

Use following test in CronParserQuartzIntegrationTest to reproduce:
@test
public void testSunToSat() {
// FAILS SUN-SAT: SUN = 7 and SAT = 6
parser.parse("0 0 12 ? * SUN-SAT");
}

Stack trace:
java.lang.IllegalArgumentException: Bad range defined! Defined range should satisfy from <= to, but was [%s, %s]
at com.cronutils.model.field.expression.Between.validate(Between.java:63)
at com.cronutils.model.field.expression.Between.(Between.java:39)
at com.cronutils.model.field.expression.Between.(Between.java:31)
at com.cronutils.parser.field.FieldParser.parseBetween(FieldParser.java:93)
at com.cronutils.parser.field.FieldParser.parse(FieldParser.java:69)
at com.cronutils.parser.field.CronParserField.parse(CronParserField.java:68)
at com.cronutils.parser.CronParser.parse(CronParser.java:96)
at com.cronutils.parser.CronParserQuartzIntegrationTest.testSunToSat(CronParserQuartzIntegrationTest.java:129)

refer to debug values below:
image

Extract DateTimeFormatBuilder to another project

Extract DateTimeFormatBuilder and related classes to another project, since is not cron functionality.
Import that project as Maven dependency, so that we can still use those classes for time formatting.

String constants (months and day of week) not working as expected

Hi,

the string constants are not working as expected. One can code "MON-FRI" for the day of the week, but "MON" for "just on mondays" doesn't work.

Same issue for the month. "JAN-FEB" is ok, but "JAN" for just january doesn't work, too.

Furthermore, some months doenst work with "from-to". With cron definition QUARTZ I've tried to pass "0 0 0 * JUL-AUG * *" - but this results in a

Exception in thread "main" java.lang.IllegalArgumentException: Values must not be empty
at org.apache.commons.lang3.Validate.notEmpty(Validate.java:300)
at com.cronutils.model.time.TimeNode.<init>(TimeNode.java:26)
at com.cronutils.model.time.ExecutionTimeBuilder.forMonthsMatching(ExecutionTimeBuilder.java:83)
at com.cronutils.model.time.ExecutionTime.forCron(ExecutionTime.java:83)
at mk.test.Main.testCronUtilsOwnDefinition(Main.java:42)
at mk.test.Main.main(Main.java:21)

My fault?

Thanks, Michael

nextExecution not working as expected

Hi,

today I've played around with cron-utils but all my efforts to get it working as I expected failed....

I've tried to get a cron expression working that "executes" every monday at 18:00. My efforts to use a custom cron definition failed, so I tried the built-in CRON4J expression....

Here is what I've did:

  // every monday at 18:00
  final String cronExpression = "0 18 * * 1";

  final CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.CRON4J);
  final CronValidator validator = new CronValidator(cronDefinition);
  System.out.println("isValid:" + validator.isValid(cronExpression));

  final CronParser parser = new CronParser(cronDefinition);
  final Cron cron = parser.parse(cronExpression);

  final ExecutionTime executionTime = ExecutionTime.forCron(cron);

  final CronDescriptor descriptor = CronDescriptor.instance(Locale.UK);
  System.out.println(descriptor.describe(cron));

  final DateTime now = DateTime.now();
  final DateTime nextExec = executionTime.nextExecution(now);
  final DateTime overNextExec = executionTime.nextExecution(nextExec);

  System.out.println("now is: " + now);
  System.out.println("next exec time: " + nextExec);
  System.out.println("over next exec time: " + overNextExec);

This results in

isValid:true
at 18:00 at Monday day
now is: 2015-07-01T17:02:07.556+02:00
next exec time: 2015-07-01T18:00:00.000+02:00
over next exec time: 2015-07-01T18:00:00.000+02:00 

As you can see, the date is always the 1st of july, whis is in fact no monday. I also don't understand why the "overnext time" is the same as the "next time".

Anything I did wrong?

Thank you, Michael

nextExecution() does not respect months (and possibly weeks)

If you write a cron expression that contains a month or day of week, nextExection() ignores it.

Example where it's supposed to fire at 11:11 on November 11th:

    CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
    CronParser cronParser = new CronParser(cronDefinition);
    ExecutionTime executionTime = ExecutionTime.forCron(cronParser.parse("0 11 11 11 11 ?"));
    CronDescriptor descriptor = CronDescriptor.instance(Locale.UK);
    System.out.println(descriptor.describe(cronParser.parse("0 11 11 11 11 ?")));
    DateTime now = DateTime.now();
    DateTime whenToExecuteNext = executionTime.nextExecution(now);
    System.out.println(whenToExecuteNext.toString("yyyy/MM/dd HH:mm:ss", Locale.ENGLISH));

output is

at 11:11 at 11 day at November month
2015/03/02 11:11:00

So it (sort of) got the descriptor right, but the nextExecution() is actually in the past.

Buggy Descriptor: Throwing ArrayIndexOutOfBoundsException and UnknownFormatConversionExceptions

Hello, is it a known issue that the descriptor is throwing weird formatting and array exceptions?

This is my code:

try{
String cronExpr = "% HERE CRON EXPRESSION %";
  CronDefinition cronDefinition =  CronDefinitionBuilder.instanceDefinitionFor(CronType.CRON4J);
  CronParser parser = new CronParser(cronDefinition);
  CronDescriptor descriptor = CronDescriptor.instance(Locale.UK);
  descriptor.describe(parser.parse(cronExpr)
}catch(Exception e){
        e.printStackTrace();
}

When I use:
*** 1,2,3,4,5,6 * 1,2,3 ***
I get:
java.lang.ArrayIndexOutOfBoundsException: 1

When I use:
* 1 1,2 * 4
I get:
java.util.UnknownFormatConversionException: Conversion = 'p'

Both examples return TRUE while validation.

More info:
CronType.CRON4J and CronType.UNIX has the same bug.
CronUtils 3.0 and 2.0 has the same bug.

I have htime-1.0, joda-time-2.4, guava-18.0, commons-lang3-3.4 in the classpath.

Could somebody try to replicate the issue?

Next execution for day of week seems to be wrong

I just started using the library, but the first test I ran seems to fail. I'm trying to specify minute, hour of day, and day of week. It looks like late in month has trouble. Using version 3.1.2. If I get some time I'll try to dig, but it'll be a bit before that happens.

See the following.

public class ScheduleHelperTest
{
DateFormat dfSimple = new SimpleDateFormat("hh:mm:ss MM/dd/yyyy a");
DateFormat df = new SimpleDateFormat("hh:mm:ss EEE, MMM dd yyyy a");

@Test
public void testBasicCron() throws ParseException
{
    printDate("3:15:00 11/20/2015 PM");
    printDate("3:15:00 11/27/2015 PM");

// printDate("3:15:00 11/29/2015 PM");
// printDate("3:15:00 11/30/2015 PM");
// printDate("3:15:00 12/01/2015 PM");
// printDate("3:15:00 12/02/2015 PM");
// printDate("3:15:00 12/29/2015 PM");
// printDate("3:15:00 12/30/2015 PM");
// printDate("3:15:00 12/31/2015 PM");
}

private void printDate(String startDate) throws ParseException
{
    Date now = dfSimple.parse(startDate);
    System.out.println("Starting: "+ df.format(now));
    printNextDate(now, "0 6 * * 0");//Sunday
    printNextDate(now, "0 6 * * 1");
    printNextDate(now, "0 6 * * 2");
    printNextDate(now, "0 6 * * 3");
    printNextDate(now, "0 6 * * 4");
    printNextDate(now, "0 6 * * 5");
    printNextDate(now, "0 6 * * 6");
}

private void printNextDate(Date now, String cronString)
{
    Date date = nextSchedule(cronString, now);
    System.out.println("Next time: " + df.format(date));
}

public static Date nextSchedule(String cronString, Date lastExecution)
{
    DateTime now = new DateTime(lastExecution);
    CronParser cronParser =new CronParser(
            CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX));
    Cron cron = cronParser.parse(cronString);

    ExecutionTime executionTime = ExecutionTime.forCron(cron);
    DateTime nextExecution = executionTime.nextExecution(now);

    return nextExecution.toDate();
}

}

Starting: 03:15:00 Fri, Nov 20 2015 PM
Next time: 06:00:00 Sun, Nov 22 2015 AM
Next time: 06:00:00 Mon, Nov 23 2015 AM <-- As expected, one day later
Next time: 06:00:00 Tue, Nov 24 2015 AM
Next time: 06:00:00 Wed, Nov 25 2015 AM
Next time: 06:00:00 Thu, Nov 26 2015 AM
Next time: 06:00:00 Fri, Nov 27 2015 AM
Next time: 06:00:00 Sat, Nov 21 2015 AM
Starting: 03:15:00 Fri, Nov 27 2015 PM
Next time: 06:00:00 Sun, Nov 29 2015 AM
Next time: 06:00:00 Mon, Dec 07 2015 AM <-- Jumps an extra week
Next time: 06:00:00 Tue, Dec 08 2015 AM
Next time: 06:00:00 Wed, Dec 02 2015 AM
Next time: 06:00:00 Thu, Dec 03 2015 AM
Next time: 06:00:00 Fri, Dec 04 2015 AM
Next time: 06:00:00 Sat, Nov 28 2015 AM

Quartz: offset from the last day of the month currently not supported

Description: Currently expressions with an offset from the last day of the month are not supported. The feature is described at Quartz tutorial.
Example:
CronParser parser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ));
parser.parse("* * * L-3 * ?");
Output: java.lang.IllegalArgumentException: java.lang.NumberFormatException: For input string: "L"
Expected behaviour: Properly parse the expression, without throwing an exception.

Better validation message

First of all thanks for sharing this project!

"Expressions size do not match registered options!" is not really helpful, wrong spelling and somewhat a technical detail.
This should be something like: "Cron expression contains x parts but we expect one of [6,7]"

Expose `ExecutionTime` as public

Why is ExecutionTime (the class) not exposed as a publicly accessible class?

It would be very handy to get access to it instead of copy+pasting the class into application code.

Parser exception handling

Parsing can throw different kinds of exceptions. It would be nice if it would always throw IllegalArgumentException

eg:
parsing * *[triple space here]* * ? throws a NumberFormatException with message For input string: ""

java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:592)
    at java.lang.Integer.parseInt(Integer.java:615)
    at com.cronutils.model.field.constraint.FieldConstraints.stringToInt(FieldConstraints.java:70)
    at com.cronutils.model.field.On.<init>(On.java:28)
    at com.cronutils.parser.field.FieldParser.parse(FieldParser.java:46)
    at com.cronutils.parser.field.CronParserField.parse(CronParserField.java:68)
    at com.cronutils.parser.CronParser.parse(CronParser.java:86)

lastExecution returns incorrect value

Here's a new unit test for ExecutionTimeIntegrationTest. The println is just for debugging.

@Test
public void testHourlyIntervalTimeFromLastExecution() throws Exception {
    DateTime now = DateTime.now();
    int hour = now.getHourOfDay();
    int previousHour = (hour > 0) ? (hour - 1) : 23;
    String quartzCronExpression = "0 0 " + previousHour + " * * ?";
    ExecutionTime executionTime = ExecutionTime.forCron(quartzCronParser.parse(quartzCronExpression));
    System.out.println(executionTime.lastExecution(now));
    assertTrue(executionTime.timeFromLastExecution(now).getStandardMinutes() <= 120);
}

lastExecution and nextExecution do not work

for everything other than a dayOfWeek value == 1, nextExecution and lastExecution do not return correct results. Example below should return a date of 9/23 while it returns 9/30. Similiarly other days return a week further then they should. Only 1 gives the correct value of 9/21. I tried with previous versions of this and although i get a different result, it is still wrong. with previous versions i always get the next day (9/19)

CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX);
CronParser parser = new CronParser(cronDefinition);
Cron myCron = parser.parse("0 3 * * 3");
DateTime now = DateTime.now();
ExecutionTime executionTime = ExecutionTime.forCron(myCron);
DateTime nextExecution = executionTime.nextExecution(now);

Week days are not recognized

The following fails as invalid cron expression:

CronParser parser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ));
ExecutionTime executionTime = ExecutionTime.forCron(parser.parse("0 0 3 ? * SAT"));

Throws java.lang.IllegalArgumentException: Invalid value. Expected some integer, found SAT

The expression was actually taken from working quartz 2.2.1 based system.

Unix crontab

Hi,
I have the following in my unix crontab :
00 21 * * * /appli/run.sh

When I executed
ExecutionTime executionTime = ExecutionTime.forCron(parser.parse(cron));

I have the following error
Class java.lang.IllegalArgumentException Message Invalid chars in expression! Expression: APPLI Invalid chars: APPLI

Does I miss somehting ?

Here is the complete source code :

   CronDefinition cronDefinition =
        CronDefinitionBuilder.defineCron()
        .withSeconds().and()
        .withMinutes().and()
        .withHours().and()
        .withDayOfMonth()
        .supportsHash().supportsL().supportsW().and()
        .withMonth().and()
        .withDayOfWeek()
        .withIntMapping(7, 0) //we support non-standard non-zero-based numbers!
        .supportsHash().supportsL().supportsW().and()
        .withYear().and()
        .lastFieldOptional()
        .instance();

    //or get a predefined instance
    cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(com.cronutils.model.CronType.QUARTZ);
    //create a parser based on provided definition
    CronParser parser = new CronParser(cronDefinition);
    DateTime now = DateTime.now();
    ExecutionTime executionTime = ExecutionTime.forCron(parser.parse(cron));
    DateTime nextExecution = executionTime.nextExecution(now);

ExecutionTime.lastExecution doesn't work

The following test case fails:

DateTime now = DateTime.now();
CronParser parser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ));
ExecutionTime executionTime = ExecutionTime.forCron(parser.parse("0 0 3 ? * 6"));
DateTime last = executionTime.lastExecution(now);
DateTime next = executionTime.nextExecution(now);
Assert.assertNotEquals(last, next);

I expected the last to be "3 AM of the nearest Saturday looking past from now" and next to be "3 AM of the nearest Saturday looking forward". Am I wrong with my expectations?

Support Java 8 time

Current implementation was developed using joda-time, since provides great date and time utils.
A new date, time and calendar API was released at Java 8. Since we want to keep compatibility with previous JDK versions, we want to maintain a branch with joda-time dependency, and another to leverage the new Java 8 API.

cron-utils fails to describe weekday list

When we select cron expression as weekly Monday and Tuesday the expression is coming like
0 0 0 ? * MON,TUE *

exception got while parsing the cron expression.

in hours tab
image

image

L option for Quartz Parser is not working

Hi

When I try t use the Quartz Parser for below expression, I got error

expression:

0 0/10 22 L * ?

Error message

Exception in thread "main" java.lang.IllegalArgumentException: Number 0 out of range [1,31]
at com.cronutils.model.field.constraint.FieldConstraints.validateInRange(FieldConstraints.java:111)
at com.cronutils.model.field.expression.FieldExpression.validate(FieldExpression.java:48)
at com.cronutils.model.field.expression.On.<init>(On.java:52)
at com.cronutils.parser.field.FieldParser.parseOn(FieldParser.java:136)
at com.cronutils.parser.field.FieldParser.parse(FieldParser.java:51)
at com.cronutils.parser.field.CronParserField.parse(CronParserField.java:68)
at com.cronutils.parser.CronParser.parse(CronParser.java:88)

I believe the issue is FieldParser/parseOn method. It set 0 for this fileds IntegerFieldValue on On class and it raises exception because DAY_OF_MONTH should be between 1-31

    if (exp.contains("L")) {
        specialChar = new SpecialCharFieldValue(SpecialChar.L);
        exp = exp.replace("L", "");
        if ("".equals(exp)) {
            expression = "0";//to avoid a NumberFormatException
        } else {
            expression = exp;
        }
    }

timeToNextExecution returns Duration evaluates to 0

Firstly very nice tool! thank you!

Now the problem:

  1. I use the tool to schedule tasks to be executed periodically
  2. The following code calculates the next time the job shall be invoked:
@Override
void schedule(AppJobManager manager, _Job job) {
    DateTime now = DateTime.now();
    ExecutionTime executionTime = ExecutionTime.forCron(cron);
    Duration nextExecution = executionTime.timeToNextExecution(now);
    long seconds = nextExecution.getStandardSeconds();
    manager.executor().schedule(job, seconds, TimeUnit.SECONDS);
}

Problem is I found it always returns 0 for the next time. Thus the job is executed huge number of times (>300) while I expected it to be executed for 1 time. The schedule method is called after the time is due and job is executed.

Build continuous delivery pipeline for SNAPSHOT artifacts

Setup a continuous delivery pipeline for SNAPSHOT artifacts to ensure they are published to Maven central with latest fixes and features being pushed to the github repository. This way, anyone depending on the latest version, would benefit from them as soon as changes are pushed.

java.lang.NoClassDefFoundError com/google/common/collect/Maps

Hello there, I am using the jar file from maven central cron-utils-1.1.2.jar

this is my code following the examples :

package com.mh.cronParser;

import com.cronutils.descriptor.CronDescriptor;
import com.cronutils.model.Cron;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinition;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.parser.CronParser;
import com.cronutils.validator.CronValidator;

import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        CronDefinition cronDefinition =
                CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);

        //create a parser based on provided definition
        CronParser parser = new CronParser(cronDefinition);
        Cron quartzCron = parser.parse("0 23 ? * * 1-5 *");
        System.out.println(quartzCron.asString());

        //create a descriptor for a specific Locale
        CronDescriptor descriptor = CronDescriptor.instance(Locale.UK);

        //parse some expression and ask descriptor for description
        String description = descriptor.describe(parser.parse("*/45 * * * * *"));
        //description will be: "every 45 seconds"

        //Validate if a string expression matches a cron definition:
        CronValidator quartzValidator = new CronValidator(cronDefinition);

        //getting a boolean result:
        quartzValidator.isValid("0 23 ? * * MON-FRI *");

        //or returning same string if valid and raising an exception if invalid
        quartzValidator.validate("0 23 ? * * MON-FRI *");
    }
}

and I got this exception when I tried to run the program

Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/collect/Maps
    at com.cronutils.model.definition.CronDefinitionBuilder.<init>(CronDefinitionBuilder.java:39)
    at com.cronutils.model.definition.CronDefinitionBuilder.defineCron(CronDefinitionBuilder.java:48)
    at com.cronutils.model.definition.CronDefinitionBuilder.quartz(CronDefinitionBuilder.java:152)
    at com.cronutils.model.definition.CronDefinitionBuilder.instanceDefinitionFor(CronDefinitionBuilder.java:188)
    at com.mh.cronParser.Main.main(Main.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: java.lang.ClassNotFoundException: com.google.common.collect.Maps
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 10 more

looks like the built jar is not fine

lastExecution can return dates in the future when cron definition contains "day of week"

For cron expressions which specify a day of the week to run on, ExecutionTime.lastExecution can return a date in the future if the last execution was in the previous month.

E.g. for cron expression "0 11 * * 1" if you try to get the last execution as of "2015-11-02T00:10:00" it will return "2015-11-16T11:00:00" rather than "2015-10-26T11:00:00" as expected.

This appear to be due to a bug in TimeNode.java which doesn't return the correct shift value when getting the nearest backward value.

It looks like a similar bug was fixed in TimeNode.getNearestForwardValue as part of issue #37

Incorrect parsing of step values: "0 1/2 * * *" -> "0 /2 * * *"

When using UNIX cron type (other not tested), the cron parser produces incorrect values for some step values (the one with slashes), e.g.:

Input Parser output Comment
0 0/1 * * * 0 * * * The hour field is missing/empty.
0 1/2 * * * 0 /2 * * * The hour field should remain 1/2.
0/1 * * * * * * * * The minute field is missing/emtpy.
1/2 * * * * /2 * * * * The minute field should remain 1/2.

Test used with cron-utils:3.1.2:

public class StepValuesTest {

    private CronParser cronParser;

    @Before
    public void setup() {
        CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX);
        cronParser = new CronParser(cronDefinition);
    }

    @Test
    public void everyEvenHourShouldBeParsedCorrectly() {
        Cron cron = cronParser.parse("0 0/1 * * *");
        assertThat(cron.asString(), anyOf(is("0 0/1 * * *"), is("0 /1 * * *"), is("0 * * * *")));
    }

    @Test
    public void everyOddHourShouldBeParsedCorrectly() {
        Cron cron = cronParser.parse("0 1/2 * * *");
        assertThat(cron.asString(), is("0 1/2 * * *"));
    }

    @Test
    public void everyEvenMinuteShouldBeParsedCorrectly() {
        Cron cron = cronParser.parse("0/1 * * * *");
        assertThat(cron.asString(), anyOf(is("0/1 * * * *"), is("/1 * * * *"), is("* * * * *")));
    }

    @Test
    public void everyOddMinuteShouldBeParsedCorrectly() {
        Cron cron = cronParser.parse("1/2 * * * *");
        assertThat(cron.asString(), is("1/2 * * * *"));
    }

}

NullPointerException with custom cronExpression without DaysOfMonth

Hi,

today I've played around with cron-utils but all my efforts to get it working as I expected failed....

I've tried to create a custom expression that contains just fields for "minute", "hour" and "dayOfWeek", so I can configure expressions like "every saturday and sunday at 18:00". But all I've got is a NPE. Her is what I've done:

  final CronDefinition cronDefinition =
          CronDefinitionBuilder.defineCron()
              .withMinutes().and()
              .withHours().and()
              .withDayOfWeek().and()
              .instance();


  // every monday at 18:00
  final String cronExpression = "0 18 1";

  final CronValidator validator = new CronValidator(cronDefinition);
  System.out.println("isValid:" + validator.isValid(cronExpression));

  final CronParser parser = new CronParser(cronDefinition);
  final Cron cron = parser.parse(cronExpression);

  final ExecutionTime executionTime = ExecutionTime.forCron(cron);

The last line throws an NPE:

Exception in thread "main" java.lang.NullPointerException
at com.cronutils.model.time.ExecutionTimeBuilder.validate(ExecutionTimeBuilder.java:114)
at com.cronutils.model.time.ExecutionTimeBuilder.forDaysOfMonthMatching(ExecutionTimeBuilder.java:100)
at com.cronutils.model.time.ExecutionTime.forCron(ExecutionTime.java:81)
at mk.test.Main.testCronUtilsOwnDefinition(Main.java:49)
at mk.test.Main.main(Main.java:21)

Is it a bug or did I make a mistake?

Thank you, Michael

NextExecution calculates wrong time

Sample cron expression

0 0/10 22 * * *

I run the core at 15:27, and it gives me the next execution time of 22:30, which should be 22:00. I believe it first look to the minute than hours, so next close value in range to 27 is 30.

İt should look first to year, month, etc, starting from bigger to smaller time unit.

Expressions containing multiple days of the week are not handled correctly.

For cron expressions where multiple days of the week are defined, the lastExecution can be wrong. For example the expression "* * * * 1,2" which should run every minute on Mondays and Tuesdays will actually be treated as running every minute on the 1st and 2nd of the month.

This appears to be due to FieldValueGeneratorFactory not handling "And" expressions correctly for Day of Week. On/Between expressions are handled by specific OnDayOfWeekValueGenerator and BetweenDayOfWeekValueGenerate, but And expressions are handled by the AndFieldValueGenerator.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.