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

org.quartz.DateBuilder Maven / Gradle / Ivy

/*
 * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 * use this file except in compliance with the License. You may obtain a copy 
 * of the License at 
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0 
 *   
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
 * License for the specific language governing permissions and limitations 
 * under the License.
 * 
 */

package org.quartz;

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

/**
 * DateBuilder is used to conveniently create 
 * java.util.Date instances that meet particular criteria.
 *  
 * 

Quartz provides a builder-style API for constructing scheduling-related * entities via a Domain-Specific Language (DSL). The DSL can best be * utilized through the usage of static imports of the methods on the classes * TriggerBuilder, JobBuilder, * DateBuilder, JobKey, TriggerKey * and the various ScheduleBuilder implementations.

* *

Client code can then use the DSL to write code such as this:

*
 *         JobDetail job = newJob(MyJob.class)
 *             .withIdentity("myJob")
 *             .build();
 *             
 *         Trigger trigger = newTrigger() 
 *             .withIdentity(triggerKey("myTrigger", "myTriggerGroup"))
 *             .withSchedule(simpleSchedule()
 *                 .withIntervalInHours(1)
 *                 .repeatForever())
 *             .startAt(futureDate(10, MINUTES))
 *             .build();
 *         
 *         scheduler.scheduleJob(job, trigger);
 * 
 *  
 * @see TriggerBuilder
 * @see JobBuilder 
 */
public class DateBuilder {

    public enum IntervalUnit { MILLISECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR };
    
    public static final int SUNDAY = 1;

    public static final int MONDAY = 2;

    public static final int TUESDAY = 3;

    public static final int WEDNESDAY = 4;

    public static final int THURSDAY = 5;

    public static final int FRIDAY = 6;

    public static final int SATURDAY = 7;

    public static final long MILLISECONDS_IN_MINUTE = 60l * 1000l;

    public static final long MILLISECONDS_IN_HOUR = 60l * 60l * 1000l;

    public static final long SECONDS_IN_MOST_DAYS = 24l * 60l * 60L;

    public static final long MILLISECONDS_IN_DAY = SECONDS_IN_MOST_DAYS * 1000l;
    
    private int month;
    private int day;
    private int year;
    private int hour;
    private int minute;
    private int second;
    private TimeZone tz;
    private Locale lc;
    
    /**
     * Create a DateBuilder, with initial settings for the current date and time in the system default timezone.
     */
    private DateBuilder() {
        Calendar cal = Calendar.getInstance();
        
        month = cal.get(Calendar.MONTH);
        day = cal.get(Calendar.DAY_OF_MONTH);
        year = cal.get(Calendar.YEAR);
        hour = cal.get(Calendar.HOUR_OF_DAY);
        minute = cal.get(Calendar.MINUTE);
        second = cal.get(Calendar.SECOND);
    }

    /**
     * Create a DateBuilder, with initial settings for the current date and time in the given timezone.
     */
    private DateBuilder(TimeZone tz) {
        Calendar cal = Calendar.getInstance(tz);
        
        this.tz = tz;
        month = cal.get(Calendar.MONTH);
        day = cal.get(Calendar.DAY_OF_MONTH);
        year = cal.get(Calendar.YEAR);
        hour = cal.get(Calendar.HOUR_OF_DAY);
        minute = cal.get(Calendar.MINUTE);
        second = cal.get(Calendar.SECOND);
    }

    /**
     * Create a DateBuilder, with initial settings for the current date and time in the given locale.
     */
    private DateBuilder(Locale lc) {
        Calendar cal = Calendar.getInstance(lc);
        
        this.lc = lc;
        month = cal.get(Calendar.MONTH);
        day = cal.get(Calendar.DAY_OF_MONTH);
        year = cal.get(Calendar.YEAR);
        hour = cal.get(Calendar.HOUR_OF_DAY);
        minute = cal.get(Calendar.MINUTE);
        second = cal.get(Calendar.SECOND);
    }

    /**
     * Create a DateBuilder, with initial settings for the current date and time in the given timezone and locale.
     */
    private DateBuilder(TimeZone tz, Locale lc) {
        Calendar cal = Calendar.getInstance(tz, lc);
        
        this.tz = tz;
        this.lc = lc;
        month = cal.get(Calendar.MONTH);
        day = cal.get(Calendar.DAY_OF_MONTH);
        year = cal.get(Calendar.YEAR);
        hour = cal.get(Calendar.HOUR_OF_DAY);
        minute = cal.get(Calendar.MINUTE);
        second = cal.get(Calendar.SECOND);
    }

    /**
     * Create a DateBuilder, with initial settings for the current date and time in the system default timezone.
     */
    public static DateBuilder newDate() {
        return new DateBuilder();
    }

    /**
     * Create a DateBuilder, with initial settings for the current date and time in the given timezone.
     */
    public static DateBuilder newDateInTimezone(TimeZone tz) {
        return new DateBuilder(tz);
    }

    /**
     * Create a DateBuilder, with initial settings for the current date and time in the given locale.
     */
    public static DateBuilder newDateInLocale(Locale lc) {
        return new DateBuilder(lc);
    }

    /**
     * Create a DateBuilder, with initial settings for the current date and time in the given timezone and locale.
     */
    public static DateBuilder newDateInTimeZoneAndLocale(TimeZone tz, Locale lc) {
        return new DateBuilder(tz, lc);
    }

    /**
     * Build the Date defined by this builder instance. 
     */
    public Date build() {
        Calendar cal = null;

        if(tz != null && lc != null)
            cal = Calendar.getInstance(tz, lc);
        else if(tz != null)
            cal = Calendar.getInstance(tz);
        else if(lc != null)
            cal = Calendar.getInstance(lc);
        else 
          cal = Calendar.getInstance();
        
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, day);
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        cal.set(Calendar.MILLISECOND, 0);
        
        return cal.getTime();
    }
    
    /**
     * Set the hour (0-23) for the Date that will be built by this builder.
     */
    public DateBuilder atHourOfDay(int atHour) {
        validateHour(atHour);
        
        this.hour = atHour;
        return this;
    }

    /**
     * Set the minute (0-59) for the Date that will be built by this builder.
     */
    public DateBuilder atMinute(int atMinute) {
        validateMinute(atMinute);
        
        this.minute = atMinute;
        return this;
    }

    /**
     * Set the second (0-59) for the Date that will be built by this builder, and truncate the milliseconds to 000.
     */
    public DateBuilder atSecond(int atSecond) {
        validateSecond(atSecond);
        
        this.second = atSecond;
        return this;
    }

    public DateBuilder atHourMinuteAndSecond(int atHour, int atMinute, int atSecond) {
        validateHour(atHour);
        validateMinute(atMinute);
        validateSecond(atSecond);
        
        this.hour = atHour;
        this.second = atSecond;
        this.minute = atMinute;
        return this;
    }
    
    /**
     * Set the day of month (1-31) for the Date that will be built by this builder.
     */
    public DateBuilder onDay(int onDay) {
        validateDayOfMonth(onDay);
        
        this.day = onDay;
        return this;
    }

    /**
     * Set the month (1-12) for the Date that will be built by this builder.
     */
    public DateBuilder inMonth(int inMonth) {
        validateMonth(inMonth);
        
        this.month = inMonth;
        return this;
    }
    
    public DateBuilder inMonthOnDay(int inMonth, int onDay) {
        validateMonth(inMonth);
        validateDayOfMonth(onDay);
        
        this.month = inMonth;
        this.day = onDay;
        return this;
    }

    /**
     * Set the year for the Date that will be built by this builder.
     */
    public DateBuilder inYear(int inYear) {
        validateYear(inYear);
        
        this.year = inYear;
        return this;
    }

    /**
     * Set the TimeZone for the Date that will be built by this builder (if "null", system default will be used)
     */
    public DateBuilder inTimeZone(TimeZone timezone) {
        this.tz = timezone;
        return this;
    }

    /**
     * Set the Locale for the Date that will be built by this builder (if "null", system default will be used)
     */
    public DateBuilder inLocale(Locale locale) {
        this.lc = locale;
        return this;
    }

    public static Date futureDate(int interval, IntervalUnit unit) {
        
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.setLenient(true);
        
        c.add(translate(unit), interval);

        return c.getTime();
    }
    

    private static int translate(IntervalUnit unit) {
        switch(unit) {
            case DAY : return Calendar.DAY_OF_YEAR;
            case HOUR : return Calendar.HOUR_OF_DAY;
            case MINUTE : return Calendar.MINUTE;
            case MONTH : return Calendar.MONTH;
            case SECOND : return Calendar.SECOND;
            case MILLISECOND : return Calendar.MILLISECOND;
            case WEEK : return Calendar.WEEK_OF_YEAR;
            case YEAR : return Calendar.YEAR;
            default : throw new IllegalArgumentException("Unknown IntervalUnit");
        }
    }

    /**
     * 

* Get a Date object that represents the given time, on * tomorrow's date. *

* * @param second * The value (0-59) to give the seconds field of the date * @param minute * The value (0-59) to give the minutes field of the date * @param hour * The value (0-23) to give the hours field of the date * @return the new date */ public static Date tomorrowAt(int hour, int minute, int second) { validateSecond(second); validateMinute(minute); validateHour(hour); Date date = new Date(); Calendar c = Calendar.getInstance(); c.setTime(date); c.setLenient(true); // advance one day c.add(Calendar.DAY_OF_YEAR, 1); c.set(Calendar.HOUR_OF_DAY, hour); c.set(Calendar.MINUTE, minute); c.set(Calendar.SECOND, second); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Get a Date object that represents the given time, on * today's date (equivalent to {@link #dateOf(int, int, int)}). *

* * @param second * The value (0-59) to give the seconds field of the date * @param minute * The value (0-59) to give the minutes field of the date * @param hour * The value (0-23) to give the hours field of the date * @return the new date */ public static Date todayAt(int hour, int minute, int second) { return dateOf(hour, minute, second); } /** *

* Get a Date object that represents the given time, on * today's date (equivalent to {@link #todayAt(int, int, int)}). *

* * @param second * The value (0-59) to give the seconds field of the date * @param minute * The value (0-59) to give the minutes field of the date * @param hour * The value (0-23) to give the hours field of the date * @return the new date */ public static Date dateOf(int hour, int minute, int second) { validateSecond(second); validateMinute(minute); validateHour(hour); Date date = new Date(); Calendar c = Calendar.getInstance(); c.setTime(date); c.setLenient(true); c.set(Calendar.HOUR_OF_DAY, hour); c.set(Calendar.MINUTE, minute); c.set(Calendar.SECOND, second); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Get a Date object that represents the given time, on the * given date. *

* * @param second * The value (0-59) to give the seconds field of the date * @param minute * The value (0-59) to give the minutes field of the date * @param hour * The value (0-23) to give the hours field of the date * @param dayOfMonth * The value (1-31) to give the day of month field of the date * @param month * The value (1-12) to give the month field of the date * @return the new date */ public static Date dateOf(int hour, int minute, int second, int dayOfMonth, int month) { validateSecond(second); validateMinute(minute); validateHour(hour); validateDayOfMonth(dayOfMonth); validateMonth(month); Date date = new Date(); Calendar c = Calendar.getInstance(); c.setTime(date); c.set(Calendar.MONTH, month - 1); c.set(Calendar.DAY_OF_MONTH, dayOfMonth); c.set(Calendar.HOUR_OF_DAY, hour); c.set(Calendar.MINUTE, minute); c.set(Calendar.SECOND, second); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Get a Date object that represents the given time, on the * given date. *

* * @param second * The value (0-59) to give the seconds field of the date * @param minute * The value (0-59) to give the minutes field of the date * @param hour * The value (0-23) to give the hours field of the date * @param dayOfMonth * The value (1-31) to give the day of month field of the date * @param month * The value (1-12) to give the month field of the date * @param year * The value (1970-2099) to give the year field of the date * @return the new date */ public static Date dateOf(int hour, int minute, int second, int dayOfMonth, int month, int year) { validateSecond(second); validateMinute(minute); validateHour(hour); validateDayOfMonth(dayOfMonth); validateMonth(month); validateYear(year); Date date = new Date(); Calendar c = Calendar.getInstance(); c.setTime(date); c.set(Calendar.YEAR, year); c.set(Calendar.MONTH, month - 1); c.set(Calendar.DAY_OF_MONTH, dayOfMonth); c.set(Calendar.HOUR_OF_DAY, hour); c.set(Calendar.MINUTE, minute); c.set(Calendar.SECOND, second); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Returns a date that is rounded to the next even hour after the current time. *

* *

* For example a current time of 08:13:54 would result in a date * with the time of 09:00:00. If the date's time is in the 23rd hour, the * date's 'day' will be promoted, and the time will be set to 00:00:00. *

* * @return the new rounded date */ public static Date evenHourDateAfterNow() { return evenHourDate(null); } /** *

* Returns a date that is rounded to the next even hour above the given * date. *

* *

* For example an input date with a time of 08:13:54 would result in a date * with the time of 09:00:00. If the date's time is in the 23rd hour, the * date's 'day' will be promoted, and the time will be set to 00:00:00. *

* * @param date * the Date to round, if null the current time will * be used * @return the new rounded date */ public static Date evenHourDate(Date date) { if (date == null) { date = new Date(); } Calendar c = Calendar.getInstance(); c.setTime(date); c.setLenient(true); c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Returns a date that is rounded to the previous even hour below the given * date. *

* *

* For example an input date with a time of 08:13:54 would result in a date * with the time of 08:00:00. *

* * @param date * the Date to round, if null the current time will * be used * @return the new rounded date */ public static Date evenHourDateBefore(Date date) { if (date == null) { date = new Date(); } Calendar c = Calendar.getInstance(); c.setTime(date); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Returns a date that is rounded to the next even minute after the current time. *

* *

* For example a current time of 08:13:54 would result in a date * with the time of 08:14:00. If the date's time is in the 59th minute, * then the hour (and possibly the day) will be promoted. *

* * @return the new rounded date */ public static Date evenMinuteDateAfterNow() { return evenMinuteDate(null); } /** *

* Returns a date that is rounded to the next even minute above the given * date. *

* *

* For example an input date with a time of 08:13:54 would result in a date * with the time of 08:14:00. If the date's time is in the 59th minute, * then the hour (and possibly the day) will be promoted. *

* * @param date * the Date to round, if null the current time will * be used * @return the new rounded date */ public static Date evenMinuteDate(Date date) { if (date == null) { date = new Date(); } Calendar c = Calendar.getInstance(); c.setTime(date); c.setLenient(true); c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Returns a date that is rounded to the previous even minute below the * given date. *

* *

* For example an input date with a time of 08:13:54 would result in a date * with the time of 08:13:00. *

* * @param date * the Date to round, if null the current time will * be used * @return the new rounded date */ public static Date evenMinuteDateBefore(Date date) { if (date == null) { date = new Date(); } Calendar c = Calendar.getInstance(); c.setTime(date); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Returns a date that is rounded to the next even second after the current time. *

* * @return the new rounded date */ public static Date evenSecondDateAfterNow() { return evenSecondDate(null); } /** *

* Returns a date that is rounded to the next even second above the given * date. *

* * @param date * the Date to round, if null the current time will * be used * @return the new rounded date */ public static Date evenSecondDate(Date date) { if (date == null) { date = new Date(); } Calendar c = Calendar.getInstance(); c.setTime(date); c.setLenient(true); c.set(Calendar.SECOND, c.get(Calendar.SECOND) + 1); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Returns a date that is rounded to the previous even second below the * given date. *

* *

* For example an input date with a time of 08:13:54.341 would result in a * date with the time of 08:13:00.000. *

* * @param date * the Date to round, if null the current time will * be used * @return the new rounded date */ public static Date evenSecondDateBefore(Date date) { if (date == null) { date = new Date(); } Calendar c = Calendar.getInstance(); c.setTime(date); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } /** *

* Returns a date that is rounded to the next even multiple of the given * minute. *

* *

* For example an input date with a time of 08:13:54, and an input * minute-base of 5 would result in a date with the time of 08:15:00. The * same input date with an input minute-base of 10 would result in a date * with the time of 08:20:00. But a date with the time 08:53:31 and an * input minute-base of 45 would result in 09:00:00, because the even-hour * is the next 'base' for 45-minute intervals. *

* *

* More examples:

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Input TimeMinute-BaseResult Time
11:16:412011:20:00
11:36:412011:40:00
11:46:412012:00:00
11:26:413011:30:00
11:36:413012:00:00
11:16:411711:17:00
11:17:411711:34:00
11:52:411712:00:00
11:52:41511:55:00
11:57:41512:00:00
11:17:41012:00:00
11:17:41111:08:00
*

* * @param date * the Date to round, if null the current time will * be used * @param minuteBase * the base-minute to set the time on * @return the new rounded date * * @see #nextGivenSecondDate(Date, int) */ public static Date nextGivenMinuteDate(Date date, int minuteBase) { if (minuteBase < 0 || minuteBase > 59) { throw new IllegalArgumentException( "minuteBase must be >=0 and <= 59"); } if (date == null) { date = new Date(); } Calendar c = Calendar.getInstance(); c.setTime(date); c.setLenient(true); if (minuteBase == 0) { c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } int minute = c.get(Calendar.MINUTE); int arItr = minute / minuteBase; int nextMinuteOccurance = minuteBase * (arItr + 1); if (nextMinuteOccurance < 60) { c.set(Calendar.MINUTE, nextMinuteOccurance); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } else { c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } } /** *

* Returns a date that is rounded to the next even multiple of the given * minute. *

* *

* The rules for calculating the second are the same as those for * calculating the minute in the method * getNextGivenMinuteDate(..). *

* * @param date the Date to round, if null the current time will * be used * @param secondBase the base-second to set the time on * @return the new rounded date * * @see #nextGivenMinuteDate(Date, int) */ public static Date nextGivenSecondDate(Date date, int secondBase) { if (secondBase < 0 || secondBase > 59) { throw new IllegalArgumentException( "secondBase must be >=0 and <= 59"); } if (date == null) { date = new Date(); } Calendar c = Calendar.getInstance(); c.setTime(date); c.setLenient(true); if (secondBase == 0) { c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } int second = c.get(Calendar.SECOND); int arItr = second / secondBase; int nextSecondOccurance = secondBase * (arItr + 1); if (nextSecondOccurance < 60) { c.set(Calendar.SECOND, nextSecondOccurance); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } else { c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return c.getTime(); } } /** * Translate a date & time from a users time zone to the another * (probably server) time zone to assist in creating a simple trigger with * the right date & time. * * @param date the date to translate * @param src the original time-zone * @param dest the destination time-zone * @return the translated date */ public static Date translateTime(Date date, TimeZone src, TimeZone dest) { Date newDate = new Date(); int offset = (dest.getOffset(date.getTime()) - src.getOffset(date.getTime())); newDate.setTime(date.getTime() - offset); return newDate; } //////////////////////////////////////////////////////////////////////////////////////////////////// public static void validateDayOfWeek(int dayOfWeek) { if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) { throw new IllegalArgumentException("Invalid day of week."); } } public static void validateHour(int hour) { if (hour < 0 || hour > 23) { throw new IllegalArgumentException( "Invalid hour (must be >= 0 and <= 23)."); } } public static void validateMinute(int minute) { if (minute < 0 || minute > 59) { throw new IllegalArgumentException( "Invalid minute (must be >= 0 and <= 59)."); } } public static void validateSecond(int second) { if (second < 0 || second > 59) { throw new IllegalArgumentException( "Invalid second (must be >= 0 and <= 59)."); } } public static void validateDayOfMonth(int day) { if (day < 1 || day > 31) { throw new IllegalArgumentException("Invalid day of month."); } } public static void validateMonth(int month) { if (month < 1 || month > 12) { throw new IllegalArgumentException( "Invalid month (must be >= 1 and <= 12."); } } private static final int MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) + 100; public static void validateYear(int year) { if (year < 0 || year > MAX_YEAR) { throw new IllegalArgumentException( "Invalid year (must be >= 0 and <= " + MAX_YEAR); } } }