Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verifying a cron expression is valid in Java

I'm writing a scheduling application in Java using Quartz. I'm using the CronTrigger, but my cron expressions are entered into a database before they are scheduled and are based on user input.

Is there a way I can verify that the cron expressions are valid when I capture them? I'd rather do this and give the user an appropriate error message than wait until the scheduler is run and I get a ParseException when I try and create the trigger. Which could be days after the user inputs the data.

like image 780
Omar Kooheji Avatar asked Mar 02 '10 12:03

Omar Kooheji


People also ask

What is a valid Cron expression?

“0 0 12 * * ?” means “At noon every day”. “0 30 21 ? * *” means “At 9:30pm every day”.

How do you parse a Cron expression in Java?

CronSequenceGenerator; final String cronExpression = "0 45 23 * * *"; final CronSequenceGenerator generator = new CronSequenceGenerator(cronExpression); final Date nextExecutionDate = generator. next(new Date()); ...and then I suggest use Joda DateTime for date comparison.

What is Cron scheduler Java?

A Cron is a time-based job scheduler. It enables our application to schedule a job to run automatically at a certain time or date. A Job (also known as a Task) is any module that you wish to run.


2 Answers

Can't you simply create a trigger without actually executing it? You could simply give appropriate feedback in case of a ParseException. If the expression is okay, persist the expression to DB.

Edit: or simply do this:

org.quartz.CronExpression.isValidExpression(expression); 
like image 162
sfussenegger Avatar answered Oct 08 '22 21:10

sfussenegger


I've modified the following code added by @ph4r05 to generate a regex as well; here's the regex:

^\s*($|#|\w+\s*=|(\?|\*|(?:[0-5]?\d)(?:(?:-|\/|\,)(?:[0-5]?\d))?(?:,(?:[0-5]?\d)(?:(?:-|\/|\,)(?:[0-5]?\d))?)*)\s+(\?|\*|(?:[0-5]?\d)(?:(?:-|\/|\,)(?:[0-5]?\d))?(?:,(?:[0-5]?\d)(?:(?:-|\/|\,)(?:[0-5]?\d))?)*)\s+(\?|\*|(?:[01]?\d|2[0-3])(?:(?:-|\/|\,)(?:[01]?\d|2[0-3]))?(?:,(?:[01]?\d|2[0-3])(?:(?:-|\/|\,)(?:[01]?\d|2[0-3]))?)*)\s+(\?|\*|(?:0?[1-9]|[12]\d|3[01])(?:(?:-|\/|\,)(?:0?[1-9]|[12]\d|3[01]))?(?:,(?:0?[1-9]|[12]\d|3[01])(?:(?:-|\/|\,)(?:0?[1-9]|[12]\d|3[01]))?)*)\s+(\?|\*|(?:[1-9]|1[012])(?:(?:-|\/|\,)(?:[1-9]|1[012]))?(?:L|W)?(?:,(?:[1-9]|1[012])(?:(?:-|\/|\,)(?:[1-9]|1[012]))?(?:L|W)?)*|\?|\*|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?(?:,(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?)*)\s+(\?|\*|(?:[0-6])(?:(?:-|\/|\,|#)(?:[0-6]))?(?:L)?(?:,(?:[0-6])(?:(?:-|\/|\,|#)(?:[0-6]))?(?:L)?)*|\?|\*|(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?(?:,(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?)*)(|\s)+(\?|\*|(?:|\d{4})(?:(?:-|\/|\,)(?:|\d{4}))?(?:,(?:|\d{4})(?:(?:-|\/|\,)(?:|\d{4}))?)*))$ 

Here's the java code:

private static String cronRegex = null;  public static String getCronRegex() {   if (cronRegex == null)   {     // numbers intervals and regex     Map<String, String> numbers = new HashMap<String, String>();     numbers.put("sec", "[0-5]?\\d");     numbers.put("min", "[0-5]?\\d");     numbers.put("hour", "[01]?\\d|2[0-3]");     numbers.put("day", "0?[1-9]|[12]\\d|3[01]");     numbers.put("month", "[1-9]|1[012]");     numbers.put("dow", "[0-6]");     numbers.put("year", "|\\d{4}");      Map<String, String> field_re = new HashMap<String, String>();      // expand regex to contain different time specifiers     for (String field : numbers.keySet())     {       String number = numbers.get(field);       String range = "(?:" + number + ")(?:(?:-|\\/|\\," +  ("dow".equals(field)? "|#" :    "") +           ")(?:" + number + "))?" +  ("dow".equals(field)? "(?:L)?" : ("month".equals(field)? "(?:L|W)?" : ""));       field_re.put(field, "\\?|\\*|" + range + "(?:," + range + ")*");     }      // add string specifiers     String monthRE = field_re.get("month");     String monthREVal =   "JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC";     String monthRERange = "(?:" + monthREVal + ")(?:(?:-)(?:" + monthREVal + "))?" ;      monthRE = monthRE +  "|\\?|\\*|" + monthRERange + "(?:," + monthRERange + ")*" ;     field_re.put("month", monthRE);      String dowRE = field_re.get("dow");     String dowREVal = "MON|TUE|WED|THU|FRI|SAT|SUN";     String dowRERange = "(?:" + dowREVal + ")(?:(?:-)(?:" + dowREVal + "))?" ;      dowRE = dowRE + "|\\?|\\*|" + dowRERange + "(?:," + dowRERange + ")*" ;     field_re.put("dow", dowRE);      StringBuilder fieldsReSB = new StringBuilder();     fieldsReSB.append("^\\s*(").append("$") //       .append("|#") //       .append("|\\w+\\s*=") //       .append("|") //       .append("(")//       .append(field_re.get("sec")).append(")\\s+(")//       .append(field_re.get("min")).append(")\\s+(")//       .append(field_re.get("hour")).append(")\\s+(")//       .append(field_re.get("day")).append(")\\s+(")//       .append(field_re.get("month")).append(")\\s+(")//       .append(field_re.get("dow")).append(")(|\\s)+(")//       .append(field_re.get("year"))//       .append(")")//       .append(")")//       .append("$");      cronRegex = fieldsReSB.toString();   }   return cronRegex; } 

I'm by no means a regex expert, but at least this seems to work on all the examples given by the quartz documentation

like image 33
Leo Avatar answered Oct 08 '22 20:10

Leo