Quartz Enterprise Job Scheduler - A richly featured, open source job scheduling library that can be integrated within virtually any Java application
—
Utility classes for date manipulation, cron expression parsing, and other common scheduling operations in Quartz. These helpers simplify complex scheduling tasks and provide convenient methods for working with time, dates, and scheduling patterns.
Fluent utility for creating and manipulating Date instances commonly used in scheduling.
/**
* Utility for convenient creation of Date instances for scheduling
*/
class DateBuilder {
/**
* Time interval units for date calculations
*/
enum IntervalUnit {
MILLISECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR
}
// Day constants (1-based, Sunday = 1)
int SUNDAY = 1;
int MONDAY = 2;
int TUESDAY = 3;
int WEDNESDAY = 4;
int THURSDAY = 5;
int FRIDAY = 6;
int SATURDAY = 7;
// Month constants (0-based, January = 0)
int JANUARY = 0;
int FEBRUARY = 1;
int MARCH = 2;
int APRIL = 3;
int MAY = 4;
int JUNE = 5;
int JULY = 6;
int AUGUST = 7;
int SEPTEMBER = 8;
int OCTOBER = 9;
int NOVEMBER = 10;
int DECEMBER = 11;
/**
* Create a new DateBuilder instance
* @return new builder instance
*/
static DateBuilder newDate();
/**
* Create a new DateBuilder instance in specified timezone
* @param tz the timezone
* @return new builder instance
*/
static DateBuilder newDateInTimezone(TimeZone tz);
/**
* Create a date for today at specified time
* @param hour hour of day (0-23)
* @param minute minute of hour (0-59)
* @param second second of minute (0-59)
* @return date for today at specified time
*/
static Date todayAt(int hour, int minute, int second);
/**
* Create a date for tomorrow at specified time
* @param hour hour of day (0-23)
* @param minute minute of hour (0-59)
* @param second second of minute (0-59)
* @return date for tomorrow at specified time
*/
static Date tomorrowAt(int hour, int minute, int second);
/**
* Create a date in the future by adding interval to current time
* @param interval the interval value
* @param unit the interval unit
* @return future date
*/
static Date futureDate(int interval, IntervalUnit unit);
/**
* Get the next date that falls on the given minute base
* @param date starting date
* @param minuteBase minute to align to (0-59)
* @return next date aligned to minute base
*/
static Date nextGivenMinuteDate(Date date, int minuteBase);
/**
* Get next date with seconds set to 0
* @param date the date to align
* @return date with seconds set to 0
*/
static Date evenSecondDate(Date date);
/**
* Get next date with minutes and seconds set to 0
* @param date the date to align
* @return date aligned to hour boundary
*/
static Date evenMinuteDate(Date date);
/**
* Get next date with hours, minutes, and seconds set to 0
* @param date the date to align
* @return date aligned to hour boundary
*/
static Date evenHourDate(Date date);
/**
* Set the year component
* @param year the year
* @return this builder for method chaining
*/
DateBuilder atYear(int year);
/**
* Set the month component
* @param month the month (0-11, use constants)
* @return this builder for method chaining
*/
DateBuilder atMonth(int month);
/**
* Set the day of month component
* @param day the day of month (1-31)
* @return this builder for method chaining
*/
DateBuilder atDay(int day);
/**
* Set the hour component
* @param hour the hour (0-23)
* @return this builder for method chaining
*/
DateBuilder atHourOfDay(int hour);
/**
* Set the minute component
* @param minute the minute (0-59)
* @return this builder for method chaining
*/
DateBuilder atMinute(int minute);
/**
* Set the second component
* @param second the second (0-59)
* @return this builder for method chaining
*/
DateBuilder atSecond(int second);
/**
* Build the Date instance
* @return the configured date
*/
Date build();
}Usage Examples:
// Quick date creation
Date now = new Date();
Date in5Minutes = DateBuilder.futureDate(5, DateBuilder.IntervalUnit.MINUTE);
Date in2Hours = DateBuilder.futureDate(2, DateBuilder.IntervalUnit.HOUR);
Date tomorrow9AM = DateBuilder.tomorrowAt(9, 0, 0);
Date today2PM = DateBuilder.todayAt(14, 0, 0);
// Date alignment
Date alignedToMinute = DateBuilder.evenSecondDate(now);
Date alignedToHour = DateBuilder.evenMinuteDate(now);
Date nextHourMark = DateBuilder.evenHourDate(now);
// Next occurrence of minute mark (e.g., :15, :30, :45)
Date next15MinuteMark = DateBuilder.nextGivenMinuteDate(now, 15);
// Complex date building
Date specificDate = DateBuilder.newDate()
.atYear(2024)
.atMonth(DateBuilder.DECEMBER)
.atDay(25)
.atHourOfDay(9)
.atMinute(30)
.atSecond(0)
.build();
// Timezone-aware date building
Date utcDate = DateBuilder.newDateInTimezone(TimeZone.getTimeZone("UTC"))
.atYear(2024)
.atMonth(DateBuilder.JANUARY)
.atDay(1)
.atHourOfDay(0)
.atMinute(0)
.atSecond(0)
.build();
// Using in trigger creation
Trigger trigger = newTrigger()
.withIdentity("delayedStart")
.startAt(DateBuilder.futureDate(30, DateBuilder.IntervalUnit.SECOND))
.endAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.HOUR))
.withSchedule(simpleSchedule()
.withIntervalInMinutes(10)
.repeatForever())
.build();Represents a specific time of day for use with daily scheduling patterns.
/**
* Represents a time of day (hour, minute, second)
*/
class TimeOfDay implements Serializable, Comparable<TimeOfDay> {
/**
* Create time from hour and minute (second defaults to 0)
* @param hour hour of day (0-23)
* @param minute minute of hour (0-59)
* @return TimeOfDay instance
*/
static TimeOfDay hourAndMinuteOfDay(int hour, int minute);
/**
* Create time from hour, minute, and second
* @param hour hour of day (0-23)
* @param minute minute of hour (0-59)
* @param second second of minute (0-59)
* @return TimeOfDay instance
*/
static TimeOfDay hourMinuteAndSecondOfDay(int hour, int minute, int second);
/**
* Get the hour component
* @return hour (0-23)
*/
int getHour();
/**
* Get the minute component
* @return minute (0-59)
*/
int getMinute();
/**
* Get the second component
* @return second (0-59)
*/
int getSecond();
/**
* Check if this time is before another time
* @param timeOfDay the other time
* @return true if this time is before the other
*/
boolean before(TimeOfDay timeOfDay);
/**
* Check if this time is after another time
* @param timeOfDay the other time
* @return true if this time is after the other
*/
boolean after(TimeOfDay timeOfDay);
/**
* Get seconds since midnight
* @return total seconds since start of day
*/
int getSecondOfDay();
/**
* Create TimeOfDay from seconds since midnight
* @param secondOfDay seconds since start of day
* @return TimeOfDay instance
*/
static TimeOfDay secondOfDay(int secondOfDay);
}Usage Examples:
// Creating time instances
TimeOfDay morning = TimeOfDay.hourAndMinuteOfDay(9, 0); // 9:00 AM
TimeOfDay lunch = TimeOfDay.hourAndMinuteOfDay(12, 30); // 12:30 PM
TimeOfDay precise = TimeOfDay.hourMinuteAndSecondOfDay(15, 45, 30); // 3:45:30 PM
// Time comparisons
if (morning.before(lunch)) {
System.out.println("Morning comes before lunch");
}
// Working with seconds
int totalSeconds = lunch.getSecondOfDay(); // Seconds since midnight
TimeOfDay reconstructed = TimeOfDay.secondOfDay(totalSeconds);
// Using in daily time interval schedules
Trigger businessHours = newTrigger()
.withSchedule(dailyTimeIntervalSchedule()
.onMondayThroughFriday()
.startingDailyAt(TimeOfDay.hourAndMinuteOfDay(9, 0))
.endingDailyAt(TimeOfDay.hourAndMinuteOfDay(17, 0))
.withIntervalInMinutes(30))
.build();Utility for parsing, validating, and evaluating cron expressions.
/**
* Represents and evaluates cron expressions for complex scheduling patterns
*/
class CronExpression implements Serializable, Cloneable {
/**
* Create a cron expression from string
* @param cronExpression the cron expression string
* @throws ParseException if expression is invalid
*/
CronExpression(String cronExpression) throws ParseException;
/**
* Validate a cron expression string
* @param cronExpression the expression to validate
* @return true if expression is valid
*/
static boolean isValidExpression(String cronExpression);
/**
* Get the cron expression string
* @return the cron expression
*/
String getCronExpression();
/**
* Check if the given date satisfies the cron expression
* @param date the date to check
* @return true if date matches the cron pattern
*/
boolean isSatisfiedBy(Date date);
/**
* Get the next valid time after the given date
* @param date the starting date
* @return next date matching the cron expression
*/
Date getNextValidTimeAfter(Date date);
/**
* Get the next invalid time after the given date
* @param date the starting date
* @return next date not matching the cron expression
*/
Date getNextInvalidTimeAfter(Date date);
/**
* Get the time zone for this cron expression
* @return the time zone
*/
TimeZone getTimeZone();
/**
* Set the time zone for this cron expression
* @param timeZone the time zone
*/
void setTimeZone(TimeZone timeZone);
/**
* Get a human-readable summary of the cron expression
* @return description of when the expression fires
*/
String getExpressionSummary();
}Usage Examples:
try {
// Create and validate cron expressions
String cronString = "0 0 12 * * ?"; // Daily at noon
if (CronExpression.isValidExpression(cronString)) {
CronExpression cron = new CronExpression(cronString);
// Set timezone
cron.setTimeZone(TimeZone.getTimeZone("America/New_York"));
// Check if current time matches
Date now = new Date();
if (cron.isSatisfiedBy(now)) {
System.out.println("Current time matches cron expression");
}
// Find next execution times
Date nextRun = cron.getNextValidTimeAfter(now);
System.out.println("Next execution: " + nextRun);
Date secondNext = cron.getNextValidTimeAfter(nextRun);
System.out.println("Following execution: " + secondNext);
// Get human-readable description
System.out.println("Schedule: " + cron.getExpressionSummary());
}
// Complex cron expressions
CronExpression businessHours = new CronExpression("0 */15 9-17 ? * MON-FRI");
CronExpression monthlyReport = new CronExpression("0 0 9 1 * ?");
CronExpression quarterlyMeeting = new CronExpression("0 0 14 1 1,4,7,10 ?");
// Calculate execution schedule
Date start = new Date();
Date end = DateBuilder.futureDate(30, DateBuilder.IntervalUnit.DAY);
List<Date> executions = new ArrayList<>();
Date next = businessHours.getNextValidTimeAfter(start);
while (next != null && next.before(end)) {
executions.add(next);
next = businessHours.getNextValidTimeAfter(next);
}
System.out.println("Found " + executions.size() + " executions in next 30 days");
} catch (ParseException e) {
System.err.println("Invalid cron expression: " + e.getMessage());
}
// Using with cron triggers
try {
CronExpression cronExpr = new CronExpression("0 30 8 ? * MON-FRI");
cronExpr.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
Trigger cronTrigger = newTrigger()
.withSchedule(cronSchedule(cronExpr))
.build();
} catch (ParseException e) {
// Handle invalid expression
}Utility methods for working with triggers and calculating firing times.
/**
* Utility methods for working with triggers
*/
class TriggerUtils {
/**
* Get the next N fire times for a trigger
* @param trigger the trigger to analyze
* @param cal optional calendar to exclude times
* @param numTimes number of fire times to calculate
* @return list of next fire times
*/
static List<Date> computeFireTimes(OperableTrigger trigger, Calendar cal, int numTimes);
/**
* Get fire times between two dates
* @param trigger the trigger to analyze
* @param cal optional calendar to exclude times
* @param from start date
* @param to end date
* @return list of fire times in range
*/
static List<Date> computeFireTimesBetween(OperableTrigger trigger, Calendar cal, Date from, Date to);
/**
* Get the final fire time for a trigger
* @param trigger the trigger to analyze
* @return final fire time or null if infinite
*/
static Date computeFinalFireTime(OperableTrigger trigger);
}Usage Examples:
// Analyze trigger firing schedule
Trigger trigger = newTrigger()
.withSchedule(cronSchedule("0 0 9-17 * * MON-FRI")) // Hourly 9-5, weekdays
.startNow()
.endAt(DateBuilder.futureDate(30, DateBuilder.IntervalUnit.DAY))
.build();
OperableTrigger operableTrigger = (OperableTrigger) trigger;
// Get next 10 fire times
List<Date> next10 = TriggerUtils.computeFireTimes(operableTrigger, null, 10);
System.out.println("Next 10 executions:");
for (Date fireTime : next10) {
System.out.println(" " + fireTime);
}
// Get fire times for this week
Date weekStart = DateBuilder.todayAt(0, 0, 0);
Date weekEnd = DateBuilder.futureDate(7, DateBuilder.IntervalUnit.DAY);
List<Date> thisWeek = TriggerUtils.computeFireTimesBetween(
operableTrigger, null, weekStart, weekEnd);
System.out.println("Executions this week: " + thisWeek.size());
// Check if trigger has finite schedule
Date finalFire = TriggerUtils.computeFinalFireTime(operableTrigger);
if (finalFire != null) {
System.out.println("Final execution: " + finalFire);
} else {
System.out.println("Trigger runs indefinitely");
}Provides information about scheduler instance capabilities and status.
/**
* Provides metadata about a scheduler instance
*/
class SchedulerMetaData {
/**
* Get the scheduler instance name
* @return scheduler name
*/
String getSchedulerName();
/**
* Get the scheduler instance ID
* @return unique instance identifier
*/
String getSchedulerInstanceId();
/**
* Get the scheduler class being used
* @return scheduler implementation class
*/
Class<?> getSchedulerClass();
/**
* Get the Quartz version
* @return version string
*/
String getVersion();
/**
* Check if scheduler is started
* @return true if scheduler is running
*/
boolean isStarted();
/**
* Check if scheduler is in standby mode
* @return true if in standby
*/
boolean isInStandbyMode();
/**
* Check if scheduler has been shutdown
* @return true if shutdown
*/
boolean isShutdown();
/**
* Get the time when scheduler was started
* @return start time or null if not started
*/
Date getRunningSince();
/**
* Get the number of jobs executed since startup
* @return executed job count
*/
int getNumberOfJobsExecuted();
/**
* Get the job store class being used
* @return job store implementation class
*/
Class<?> getJobStoreClass();
/**
* Check if job store supports persistence
* @return true if jobs are persisted
*/
boolean isJobStoreSupportsPersistence();
/**
* Check if job store is clustered
* @return true if clustering is enabled
*/
boolean isJobStoreClustered();
/**
* Get the thread pool class being used
* @return thread pool implementation class
*/
Class<?> getThreadPoolClass();
/**
* Get the thread pool size
* @return number of threads available for job execution
*/
int getThreadPoolSize();
}Usage Examples:
// Get scheduler information
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
SchedulerMetaData metaData = scheduler.getMetaData();
// Display basic information
System.out.println("Scheduler Information:");
System.out.println(" Name: " + metaData.getSchedulerName());
System.out.println(" Instance ID: " + metaData.getSchedulerInstanceId());
System.out.println(" Version: " + metaData.getVersion());
System.out.println(" Started: " + metaData.isStarted());
if (metaData.getRunningSince() != null) {
System.out.println(" Running since: " + metaData.getRunningSince());
System.out.println(" Jobs executed: " + metaData.getNumberOfJobsExecuted());
}
// Display configuration information
System.out.println("\nConfiguration:");
System.out.println(" Scheduler class: " + metaData.getSchedulerClass().getSimpleName());
System.out.println(" Job store: " + metaData.getJobStoreClass().getSimpleName());
System.out.println(" Persistent: " + metaData.isJobStoreSupportsPersistence());
System.out.println(" Clustered: " + metaData.isJobStoreClustered());
System.out.println(" Thread pool: " + metaData.getThreadPoolClass().getSimpleName());
System.out.println(" Thread count: " + metaData.getThreadPoolSize());
// Health check based on metadata
public boolean isSchedulerHealthy(Scheduler scheduler) throws SchedulerException {
SchedulerMetaData metaData = scheduler.getMetaData();
// Check if scheduler is running
if (!metaData.isStarted() || metaData.isShutdown()) {
return false;
}
// Check if it's been running for reasonable time
Date runningSince = metaData.getRunningSince();
if (runningSince != null) {
long runningTime = System.currentTimeMillis() - runningSince.getTime();
if (runningTime < 1000) { // Less than 1 second
return false; // Might still be starting up
}
}
// Check thread pool size
if (metaData.getThreadPoolSize() < 1) {
return false;
}
return true;
}Container for sharing application data across jobs within a scheduler instance.
/**
* Holds application context data for scheduler instance
* Extends Map for convenient data access
*/
class SchedulerContext extends StringKeyDirtyFlagMap {
/**
* Create empty scheduler context
*/
SchedulerContext();
/**
* Create scheduler context with initial data
* @param map initial context data
*/
SchedulerContext(Map<?, ?> map);
// Inherits all Map methods for data manipulation
// Plus type-safe accessors similar to JobDataMap
}Usage Examples:
// Setting up scheduler context
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
SchedulerContext context = scheduler.getContext();
// Store application-wide configuration
context.put("applicationVersion", "2.1.0");
context.put("environment", "production");
context.put("databaseUrl", "jdbc:postgresql://db.example.com/app");
context.put("maxRetries", 3);
context.put("emailService", emailServiceInstance);
// Jobs can access scheduler context
public class ReportJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
// Access scheduler context
SchedulerContext schedulerContext = context.getScheduler().getContext();
String version = (String) schedulerContext.get("applicationVersion");
String environment = (String) schedulerContext.get("environment");
EmailService emailService = (EmailService) schedulerContext.get("emailService");
// Use shared resources
generateReport(version, environment, emailService);
}
private void generateReport(String version, String env, EmailService emailService) {
// Implementation using shared context
}
}
// Updating context at runtime
public void updateConfiguration(Scheduler scheduler, String newDbUrl) throws SchedulerException {
SchedulerContext context = scheduler.getContext();
context.put("databaseUrl", newDbUrl);
// All subsequently executed jobs will see the new value
}Base class for JobKey and TriggerKey providing identity and comparison functionality.
/**
* Base class for keys that identify jobs and triggers
*/
abstract class Key<T> implements Serializable, Comparable<Key<T>> {
String DEFAULT_GROUP = "DEFAULT";
/**
* Get the key name
* @return the name component of the key
*/
String getName();
/**
* Get the key group
* @return the group component of the key
*/
String getGroup();
/**
* Compare keys for ordering
* @param other the other key
* @return comparison result
*/
int compareTo(Key<T> other);
/**
* Check equality with another key
* @param obj the other object
* @return true if keys are equal
*/
boolean equals(Object obj);
/**
* Get hash code for the key
* @return hash code based on name and group
*/
int hashCode();
/**
* Get string representation
* @return formatted string with group and name
*/
String toString();
}Usage Examples:
// Key comparison and sorting
List<JobKey> jobKeys = Arrays.asList(
jobKey("jobA", "group1"),
jobKey("jobB", "group1"),
jobKey("jobA", "group2")
);
// Sort keys (by group first, then name)
Collections.sort(jobKeys);
// Key equality
JobKey key1 = jobKey("myJob", "myGroup");
JobKey key2 = jobKey("myJob", "myGroup");
System.out.println(key1.equals(key2)); // true
// Using keys in collections
Set<JobKey> uniqueKeys = new HashSet<>();
uniqueKeys.add(key1);
uniqueKeys.add(key2); // Won't add duplicate
Map<JobKey, JobDetail> jobMap = new HashMap<>();
jobMap.put(key1, jobDetail);
// Key string representation
System.out.println(key1.toString()); // "myGroup.myJob"Utility methods for working with triggers and trigger calculations.
/**
* Utility class for trigger-related operations
*/
class TriggerUtils {
/**
* Get the next N fire times for a trigger
* @param trigger the trigger to calculate for
* @param cal optional calendar for exclusions
* @param numTimes number of fire times to calculate
* @return list of future fire times
*/
static List<Date> computeFireTimes(OperableTrigger trigger, Calendar cal, int numTimes);
/**
* Get fire times between two dates
* @param trigger the trigger to calculate for
* @param cal optional calendar for exclusions
* @param from start date
* @param to end date
* @return list of fire times in the range
*/
static List<Date> computeFireTimesBetween(OperableTrigger trigger, Calendar cal, Date from, Date to);
/**
* Get the final fire time for a trigger
* @param trigger the trigger
* @return the final fire time, or null if infinite
*/
static Date computeEndTimeToAllowParticularNumberOfFirings(OperableTrigger trigger, Calendar cal, int numTimes);
/**
* Make a trigger that will fire at specific times
* @param fireTimes list of times when trigger should fire
* @return a SimpleTrigger configured for the fire times
*/
static OperableTrigger makeEvenlySpacedDateTrigger(Date[] fireTimes);
}Utility for parsing configuration properties with type conversion.
/**
* Utility for parsing configuration properties
*/
class PropertiesParser {
/**
* Create parser for properties
* @param props the properties to parse
*/
PropertiesParser(Properties props);
/**
* Get string property with optional default
* @param name property name
* @param defaultValue default if not found
* @return property value or default
*/
String getStringProperty(String name, String defaultValue);
/**
* Get required string property
* @param name property name
* @return property value
* @throws SchedulerException if property not found
*/
String getStringProperty(String name) throws SchedulerException;
/**
* Get boolean property
* @param name property name
* @param defaultValue default if not found
* @return boolean value
*/
boolean getBooleanProperty(String name, boolean defaultValue);
/**
* Get integer property
* @param name property name
* @param defaultValue default if not found
* @return integer value
*/
int getIntProperty(String name, int defaultValue);
/**
* Get long property
* @param name property name
* @param defaultValue default if not found
* @return long value
*/
long getLongProperty(String name, long defaultValue);
/**
* Get float property
* @param name property name
* @param defaultValue default if not found
* @return float value
*/
float getFloatProperty(String name, float defaultValue);
/**
* Get double property
* @param name property name
* @param defaultValue default if not found
* @return double value
*/
double getDoubleProperty(String name, double defaultValue);
/**
* Get property names with a given prefix
* @param prefix the prefix to match
* @return array of matching property names
*/
String[] getPropertyNames(String prefix);
/**
* Get properties with a given prefix as a new Properties object
* @param prefix the prefix to match
* @return Properties containing matching entries
*/
Properties getPropertyGroup(String prefix);
/**
* Get properties with prefix, removing the prefix from keys
* @param prefix the prefix to match and remove
* @param stripPrefix whether to remove prefix from keys
* @return Properties with prefix removed from keys
*/
Properties getPropertyGroup(String prefix, boolean stripPrefix);
}Utility methods for class loading and reflection operations.
/**
* Utility class for class loading operations
*/
class ClassUtils {
/**
* Load a class using the thread context class loader
* @param className fully qualified class name
* @return the loaded class
* @throws ClassNotFoundException if class not found
*/
static Class<?> loadClass(String className) throws ClassNotFoundException;
/**
* Load a class using a specific class loader
* @param className fully qualified class name
* @param classLoader the class loader to use
* @return the loaded class
* @throws ClassNotFoundException if class not found
*/
static Class<?> loadClass(String className, ClassLoader classLoader) throws ClassNotFoundException;
/**
* Create an instance of a class
* @param className fully qualified class name
* @return new instance of the class
* @throws Exception if instantiation fails
*/
static Object instantiateClass(String className) throws Exception;
/**
* Create an instance using a specific class loader
* @param className fully qualified class name
* @param classLoader the class loader to use
* @return new instance of the class
* @throws Exception if instantiation fails
*/
static Object instantiateClass(String className, ClassLoader classLoader) throws Exception;
/**
* Check if a class is available in the classpath
* @param className fully qualified class name
* @return true if class can be loaded
*/
static boolean isClassAvailable(String className);
/**
* Get the thread context class loader
* @return the current thread's context class loader
*/
static ClassLoader getThreadContextClassLoader();
/**
* Set the thread context class loader
* @param classLoader the class loader to set
*/
static void setThreadContextClassLoader(ClassLoader classLoader);
}Map implementation that tracks modifications for change detection.
/**
* Map that tracks whether its contents have been modified
* @param <K> key type
* @param <V> value type
*/
class DirtyFlagMap<K, V> extends HashMap<K, V> {
/**
* Create empty dirty flag map
*/
DirtyFlagMap();
/**
* Create dirty flag map with initial data
* @param initialCapacity initial capacity
*/
DirtyFlagMap(int initialCapacity);
/**
* Create dirty flag map from existing map
* @param map initial data
*/
DirtyFlagMap(Map<? extends K, ? extends V> map);
/**
* Check if map has been modified since last clearDirtyFlag()
* @return true if map has been modified
*/
boolean isDirty();
/**
* Clear the dirty flag
*/
void clearDirtyFlag();
/**
* Get map of all modified entries since last clearDirtyFlag()
* @return map of modified entries
*/
Map<K, V> getWrappedMap();
// Overrides all modification methods to set dirty flag
}String-keyed version of DirtyFlagMap with type-safe accessors.
/**
* String-keyed dirty flag map with type-safe accessors
*/
class StringKeyDirtyFlagMap extends DirtyFlagMap<String, Object> {
/**
* Create empty string key dirty flag map
*/
StringKeyDirtyFlagMap();
/**
* Create from existing map
* @param map initial data
*/
StringKeyDirtyFlagMap(Map<?, ?> map);
/**
* Put string value
* @param key the key
* @param value the string value
* @return previous value
*/
Object putAsString(String key, String value);
/**
* Get value as string
* @param key the key
* @return value as string or null
*/
String getString(String key);
/**
* Get boolean value
* @param key the key
* @return boolean value or false if not found
*/
boolean getBoolean(String key);
/**
* Get boolean value with default
* @param key the key
* @param defaultValue default value if not found
* @return boolean value or default
*/
boolean getBooleanValue(String key, boolean defaultValue);
/**
* Get byte value
* @param key the key
* @return byte value or 0 if not found
*/
byte getByte(String key);
/**
* Get character value
* @param key the key
* @return character value or null character if not found
*/
char getChar(String key);
/**
* Get double value
* @param key the key
* @return double value or 0.0 if not found
*/
double getDouble(String key);
/**
* Get float value
* @param key the key
* @return float value or 0.0f if not found
*/
float getFloat(String key);
/**
* Get integer value
* @param key the key
* @return integer value or 0 if not found
*/
int getInt(String key);
/**
* Get integer value with default
* @param key the key
* @param defaultValue default value if not found
* @return integer value or default
*/
int getIntValue(String key, int defaultValue);
/**
* Get long value
* @param key the key
* @return long value or 0L if not found
*/
long getLong(String key);
/**
* Get long value with default
* @param key the key
* @param defaultValue default value if not found
* @return long value or default
*/
long getLongValue(String key, long defaultValue);
/**
* Get short value
* @param key the key
* @return short value or 0 if not found
*/
short getShort(String key);
}Usage Examples:
// TriggerUtils usage
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withSchedule(simpleSchedule()
.withIntervalInHours(6)
.withRepeatCount(10))
.build();
// Calculate next 5 fire times
List<Date> fireTimes = TriggerUtils.computeFireTimes(trigger, null, 5);
for (Date fireTime : fireTimes) {
System.out.println("Will fire at: " + fireTime);
}
// Calculate fire times in a date range
Date startDate = new Date();
Date endDate = DateBuilder.futureDate(30, DateBuilder.IntervalUnit.DAY);
List<Date> fireTimesInRange = TriggerUtils.computeFireTimesBetween(trigger, null, startDate, endDate);
// PropertiesParser usage
Properties props = new Properties();
props.setProperty("app.name", "MyScheduler");
props.setProperty("app.threadCount", "10");
props.setProperty("app.enabled", "true");
props.setProperty("app.timeout", "30.5");
PropertiesParser parser = new PropertiesParser(props);
String appName = parser.getStringProperty("app.name", "DefaultApp");
int threadCount = parser.getIntProperty("app.threadCount", 5);
boolean enabled = parser.getBooleanProperty("app.enabled", false);
double timeout = parser.getDoubleProperty("app.timeout", 60.0);
// Get all properties with prefix
Properties appProps = parser.getPropertyGroup("app.", true);
// Results in: name=MyScheduler, threadCount=10, enabled=true, timeout=30.5
// ClassUtils usage
try {
// Load class dynamically
Class<?> jobClass = ClassUtils.loadClass("com.example.MyJob");
// Create instance
Job jobInstance = (Job) ClassUtils.instantiateClass("com.example.MyJob");
// Check if class exists
if (ClassUtils.isClassAvailable("com.optional.OptionalFeature")) {
// Use optional feature
}
} catch (Exception e) {
System.err.println("Failed to load class: " + e.getMessage());
}
// DirtyFlagMap usage
DirtyFlagMap<String, String> config = new DirtyFlagMap<>();
config.put("setting1", "value1");
config.put("setting2", "value2");
System.out.println("Is dirty: " + config.isDirty()); // true
config.clearDirtyFlag();
System.out.println("Is dirty: " + config.isDirty()); // false
config.put("setting3", "value3");
System.out.println("Is dirty: " + config.isDirty()); // true
// StringKeyDirtyFlagMap usage (like JobDataMap)
StringKeyDirtyFlagMap data = new StringKeyDirtyFlagMap();
data.put("count", "100");
data.put("enabled", "true");
data.put("rate", "3.14");
// Type-safe accessors
int count = data.getInt("count"); // 100
boolean enabled = data.getBoolean("enabled"); // true
double rate = data.getDouble("rate"); // 3.14
String missing = data.getString("missing"); // null
// With defaults
int defaultCount = data.getIntValue("missingCount", 50); // 50
boolean defaultEnabled = data.getBooleanValue("missingEnabled", false); // falseInstall with Tessl CLI
npx tessl i tessl/maven-org-quartz-scheduler--quartz