I have a cron \"time definition\"
1 * * * * (every hour at xx:01)
2 5 * * * (every day at 05:02)
0 4 3 * * (every third day of the month at 04:00)
* 2 * * 5
My answer is not unique. Just a replica of @BlaM answer written in java because PHP's date and time is a bit different from Java.
This program assumes that the CRON expression is simple. It can only contain digits or *.
Minute = 0-60
Hour = 0-23
Day = 1-31
MONTH = 1-12 where 1 = January.
WEEKDAY = 1-7 where 1 = Sunday.
Code:
package main;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CronPredict
{
public static void main(String[] args)
{
String cronExpression = "5 3 27 3 3 ls -la > a.txt";
CronPredict cronPredict = new CronPredict();
String[] parsed = cronPredict.parseCronExpression(cronExpression);
System.out.println(cronPredict.getNextExecution(parsed).getTime().toString());
}
//This method takes a cron string and separates entities like minutes, hours, etc.
public String[] parseCronExpression(String cronExpression)
{
String[] parsedExpression = null;
String cronPattern = "^([0-9]|[1-5][0-9]|\\*)\\s([0-9]|1[0-9]|2[0-3]|\\*)\\s"
+ "([1-9]|[1-2][0-9]|3[0-1]|\\*)\\s([1-9]|1[0-2]|\\*)\\s"
+ "([1-7]|\\*)\\s(.*)$";
Pattern cronRegex = Pattern.compile(cronPattern);
Matcher matcher = cronRegex.matcher(cronExpression);
if(matcher.matches())
{
String minute = matcher.group(1);
String hour = matcher.group(2);
String day = matcher.group(3);
String month = matcher.group(4);
String weekday = matcher.group(5);
String command = matcher.group(6);
parsedExpression = new String[6];
parsedExpression[0] = minute;
parsedExpression[1] = hour;
parsedExpression[2] = day;
//since java's month start's from 0 as opposed to PHP which starts from 1.
parsedExpression[3] = month.equals("*") ? month : (Integer.parseInt(month) - 1) + "";
parsedExpression[4] = weekday;
parsedExpression[5] = command;
}
return parsedExpression;
}
public Calendar getNextExecution(String[] job)
{
Calendar cron = Calendar.getInstance();
cron.add(Calendar.MINUTE, 1);
cron.set(Calendar.MILLISECOND, 0);
cron.set(Calendar.SECOND, 0);
int done = 0;
//Loop because some dates are not valid.
//e.g. March 29 which is a Friday may never come for atleast next 1000 years.
//We do not want to keep looping. Also it protects against invalid dates such as feb 30.
while(done < 100)
{
if(!job[0].equals("*") && cron.get(Calendar.MINUTE) != Integer.parseInt(job[0]))
{
if(cron.get(Calendar.MINUTE) > Integer.parseInt(job[0]))
{
cron.add(Calendar.HOUR_OF_DAY, 1);
}
cron.set(Calendar.MINUTE, Integer.parseInt(job[0]));
}
if(!job[1].equals("*") && cron.get(Calendar.HOUR_OF_DAY) != Integer.parseInt(job[1]))
{
if(cron.get(Calendar.HOUR_OF_DAY) > Integer.parseInt(job[1]))
{
cron.add(Calendar.DAY_OF_MONTH, 1);
}
cron.set(Calendar.HOUR_OF_DAY, Integer.parseInt(job[1]));
cron.set(Calendar.MINUTE, 0);
}
if(!job[4].equals("*") && cron.get(Calendar.DAY_OF_WEEK) != Integer.parseInt(job[4]))
{
Date previousDate = cron.getTime();
cron.set(Calendar.DAY_OF_WEEK, Integer.parseInt(job[4]));
Date newDate = cron.getTime();
if(newDate.before(previousDate))
{
cron.add(Calendar.WEEK_OF_MONTH, 1);
}
cron.set(Calendar.HOUR_OF_DAY, 0);
cron.set(Calendar.MINUTE, 0);
}
if(!job[2].equals("*") && cron.get(Calendar.DAY_OF_MONTH) != Integer.parseInt(job[2]))
{
if(cron.get(Calendar.DAY_OF_MONTH) > Integer.parseInt(job[2]))
{
cron.add(Calendar.MONTH, 1);
}
cron.set(Calendar.DAY_OF_MONTH, Integer.parseInt(job[2]));
cron.set(Calendar.HOUR_OF_DAY, 0);
cron.set(Calendar.MINUTE, 0);
}
if(!job[3].equals("*") && cron.get(Calendar.MONTH) != Integer.parseInt(job[3]))
{
if(cron.get(Calendar.MONTH) > Integer.parseInt(job[3]))
{
cron.add(Calendar.YEAR, 1);
}
cron.set(Calendar.MONTH, Integer.parseInt(job[3]));
cron.set(Calendar.DAY_OF_MONTH, 1);
cron.set(Calendar.HOUR_OF_DAY, 0);
cron.set(Calendar.MINUTE, 0);
}
done = (job[0].equals("*") || cron.get(Calendar.MINUTE) == Integer.parseInt(job[0])) &&
(job[1].equals("*") || cron.get(Calendar.HOUR_OF_DAY) == Integer.parseInt(job[1])) &&
(job[2].equals("*") || cron.get(Calendar.DAY_OF_MONTH) == Integer.parseInt(job[2])) &&
(job[3].equals("*") || cron.get(Calendar.MONTH) == Integer.parseInt(job[3])) &&
(job[4].equals("*") || cron.get(Calendar.DAY_OF_WEEK) == Integer.parseInt(job[4])) ? 100 : (done + 1);
}
return cron;
}
}