All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.sauronsoftware.cron4j.Predictor Maven / Gradle / Ivy

/*
 * cron4j - A pure Java cron-like scheduler
 * 
 * Copyright (C) 2007-2010 Carlo Pelliccia (www.sauronsoftware.it)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version
 * 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License 2.1 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License version 2.1 along with this program.
 * If not, see .
 */
package it.sauronsoftware.cron4j;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

/**
 * 

* A predictor is able to predict when a scheduling pattern will be matched. *

*

* Suppose you want to know when the scheduler will execute a task scheduled * with the pattern 0 3 * jan-jun,sep-dec mon-fri. You can predict the * next n execution of the task using a Predictor instance: *

* *
 * String pattern = "0 3 * jan-jun,sep-dec mon-fri";
 * Predictor p = new Predictor(pattern);
 * for (int i = 0; i < n; i++) {
 * 	System.out.println(p.nextMatchingDate());
 * }
 * 
* * @author Carlo Pelliccia * @since 1.1 */ public class Predictor { /** * The scheduling pattern on which the predictor works. */ private SchedulingPattern schedulingPattern; /** * The start time for the next prediction. */ private long time; /** * The time zone for the prediction. */ private TimeZone timeZone = TimeZone.getDefault(); /** * It builds a predictor with the given scheduling pattern and start time. * * @param schedulingPattern * The pattern on which the prediction will be based. * @param start * The start time of the prediction. * @throws InvalidPatternException * In the given scheduling pattern isn't valid. */ public Predictor(String schedulingPattern, long start) throws InvalidPatternException { this.schedulingPattern = new SchedulingPattern(schedulingPattern); this.time = (start / (1000 * 60)) * 1000 * 60; } /** * It builds a predictor with the given scheduling pattern and start time. * * @param schedulingPattern * The pattern on which the prediction will be based. * @param start * The start time of the prediction. * @throws InvalidPatternException * In the given scheduling pattern isn't valid. */ public Predictor(String schedulingPattern, Date start) throws InvalidPatternException { this(schedulingPattern, start.getTime()); } /** * It builds a predictor with the given scheduling pattern and the current * system time as the prediction start time. * * @param schedulingPattern * The pattern on which the prediction will be based. * @throws InvalidPatternException * In the given scheduling pattern isn't valid. */ public Predictor(String schedulingPattern) throws InvalidPatternException { this(schedulingPattern, System.currentTimeMillis()); } /** * It builds a predictor with the given scheduling pattern and start time. * * @param schedulingPattern * The pattern on which the prediction will be based. * @param start * The start time of the prediction. * @since 2.0 */ public Predictor(SchedulingPattern schedulingPattern, long start) { this.schedulingPattern = schedulingPattern; this.time = (start / (1000 * 60)) * 1000 * 60; } /** * It builds a predictor with the given scheduling pattern and start time. * * @param schedulingPattern * The pattern on which the prediction will be based. * @param start * The start time of the prediction. * @since 2.0 */ public Predictor(SchedulingPattern schedulingPattern, Date start) { this(schedulingPattern, start.getTime()); } /** * It builds a predictor with the given scheduling pattern and the current * system time as the prediction start time. * * @param schedulingPattern * The pattern on which the prediction will be based. * @since 2.0 */ public Predictor(SchedulingPattern schedulingPattern) { this(schedulingPattern, System.currentTimeMillis()); } /** * Sets the time zone for predictions. * * @param timeZone * The time zone for predictions. * @since 2.2.5 */ public void setTimeZone(TimeZone timeZone) { this.timeZone = timeZone; } /** * It returns the next matching moment as a millis value. * * @return The next matching moment as a millis value. */ public synchronized long nextMatchingTime() { // Go a minute ahead. time += 60000; // Is it matching? if (schedulingPattern.match(time)) { return time; } // Go through the matcher groups. int size = schedulingPattern.matcherSize; long[] times = new long[size]; for (int k = 0; k < size; k++) { // Ok, split the time! GregorianCalendar c = new GregorianCalendar(); c.setTimeInMillis(time); c.setTimeZone(timeZone); int minute = c.get(Calendar.MINUTE); int hour = c.get(Calendar.HOUR_OF_DAY); int dayOfMonth = c.get(Calendar.DAY_OF_MONTH); int month = c.get(Calendar.MONTH); int year = c.get(Calendar.YEAR); // Gets the matchers. ValueMatcher minuteMatcher = (ValueMatcher) schedulingPattern.minuteMatchers.get(k); ValueMatcher hourMatcher = (ValueMatcher) schedulingPattern.hourMatchers.get(k); ValueMatcher dayOfMonthMatcher = (ValueMatcher) schedulingPattern.dayOfMonthMatchers.get(k); ValueMatcher dayOfWeekMatcher = (ValueMatcher) schedulingPattern.dayOfWeekMatchers.get(k); ValueMatcher monthMatcher = (ValueMatcher) schedulingPattern.monthMatchers.get(k); for (;;) { // day of week for (;;) { // month for (;;) { // day of month for (;;) { // hour for (;;) { // minutes if (minuteMatcher.match(minute)) { break; } else { minute++; if (minute > 59) { minute = 0; hour++; } } } if (hour > 23) { hour = 0; dayOfMonth++; } if (hourMatcher.match(hour)) { break; } else { hour++; minute = 0; } } if (dayOfMonth > 31) { dayOfMonth = 1; month++; } if (month > Calendar.DECEMBER) { month = Calendar.JANUARY; year++; } if (dayOfMonthMatcher instanceof DayOfMonthValueMatcher) { DayOfMonthValueMatcher aux = (DayOfMonthValueMatcher) dayOfMonthMatcher; if (aux.match(dayOfMonth, month + 1, c.isLeapYear(year))) { break; } else { dayOfMonth++; hour = 0; minute = 0; } } else if (dayOfMonthMatcher.match(dayOfMonth)) { break; } else { dayOfMonth++; hour = 0; minute = 0; } } if (monthMatcher.match(month + 1)) { break; } else { month++; dayOfMonth = 1; hour = 0; minute = 0; } } // Is this ok? c = new GregorianCalendar(); c.setTimeZone(timeZone); c.set(Calendar.MINUTE, minute); c.set(Calendar.HOUR_OF_DAY, hour); c.set(Calendar.DAY_OF_MONTH, dayOfMonth); c.set(Calendar.MONTH, month); c.set(Calendar.YEAR, year); // Day-of-month/month/year compatibility check. int oldDayOfMonth = dayOfMonth; int oldMonth = month; int oldYear = year; dayOfMonth = c.get(Calendar.DAY_OF_MONTH); month = c.get(Calendar.MONTH); year = c.get(Calendar.YEAR); if (month != oldMonth || dayOfMonth != oldDayOfMonth || year != oldYear) { // Take another spin! continue; } // Day of week. int dayOfWeek = c.get(Calendar.DAY_OF_WEEK); if (dayOfWeekMatcher.match(dayOfWeek - 1)) { break; } else { dayOfMonth++; hour = 0; minute = 0; if (dayOfMonth > 31) { dayOfMonth = 1; month++; if (month > Calendar.DECEMBER) { month = Calendar.JANUARY; year++; } } } } // Seems it matches! times[k] = (c.getTimeInMillis() / (1000 * 60)) * 1000 * 60; } // Which one? long min = Long.MAX_VALUE; for (int k = 0; k < size; k++) { if (times[k] < min) { min = times[k]; } } // Updates the object current time value. time = min; // Here it is. return time; } /** * It returns the next matching moment as a {@link Date} object. * * @return The next matching moment as a {@link Date} object. */ public synchronized Date nextMatchingDate() { return new Date(nextMatchingTime()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy