周期(实现了每天,每周,每月,每年的间隔一定时间重复执行的周期)

来源:互联网 发布:linux oracle 编辑:程序博客网 时间:2024/05/29 07:01

import java.util.Calendar;import java.util.Date;/** * 周期<br> * 实现了每天,每周,每月,每年的间隔一定时间重复执行的周期<br> * <pre> * // 每天2点执行1次 * Period.getDailyOncePeriod(2*60*60*1000); * // 每周3的5点执行1次 * Period.getWeeklyOncePeriod((3*24+5)*60*60*1000); * // 每天隔2小时1次 * Period.getDailyPeriod(2*60*60*1000); * // 每天3点-8点隔1小时1次(6表示每天仅执行6次, 6=8-3+1) * Period.getDailyPeriod(1*60*60*1000, 3*60*60*1000, 6); * </pre> * 输入参数计算单位的自动转换<br> * <pre> * // 每天2点执行1次(Period.HOUR=以小时为时间单位) * Period.HOUR.getDailyOncePeriod(2); * // 每天隔半小时1次(Period.MINUTE=以分钟为时间单位) * Period.MINUTE.getDailyPeriod(30); * </pre> * @author zhaohuihua */public class Period {    /** 一天的毫秒数 **/    private static final long ONEDAY = 24 * 60 * 60 * 1000L;    /** 每天的周期 **/    public static final int DAILY = 0;    /** 每周的周期 **/    public static final int WEEKLY = 1;    /** 每月的周期 **/    public static final int MONTHLY = 2;    /** 每年的周期 **/    public static final int YEARLY = 3;    /** 以天计算的时间单位, 该单位的所有方法的时间参数都以天表示 **/    public static final Unit DAY = new Unit(ONEDAY);    /** 以小时计算的时间单位, 该单位的所有方法的时间参数都以小时表示 **/    public static final Unit HOUR = new Unit(60 * 60 * 1000L);    /** 以分计算的时间单位, 该单位的所有方法的时间参数都以分表示 **/    public static final Unit MINUTE = new Unit(60 * 1000L);    /** 以秒计算的时间单位, 该单位的所有方法的时间参数都以秒表示 **/    public static final Unit SECOND = new Unit(1000L);    /** 以毫秒计算的时间单位, 该单位的所有方法的时间参数都以毫秒表示 **/    public static final Unit MILLISECOND = new Unit(1L);    /** 类型(0.DAILY|1.WEEKLY|2.MONTHLY|3.YEARLY) **/    private final int type;    /** 间隔时间 **/    private final long interval;    /** 偏移时间(从每个周期的什么时间开始) **/    private final long offset;    /** 执行次数(每个周期的最大执行次数), 0表示无限制 **/    private final int times;    /**     * 计算时的参照时间点<br>     * 如果为null, 每次计算时读取系统时间, 并计算其下一时间点<br>     * 如果指定了时间, 则计算该固定时间点的下一时间点     */    private Date date;    /** 是否输出日志(用于测试) **/    private static boolean log = false;    /**     * 私有全参数构造函数     * @param type 类型(DAILY | WEEKLY | MONTHLY | YEARLY)     * @param interval 间隔时间     * @param offset 偏移时间(从每个周期的什么时间开始)     * @param times 执行次数(每个周期的最大执行次数), 0表示无限制     * @param date 计算时的参照时间点<br>     * 如果为null, 每次计算时读取系统时间, 并计算其下一时间点<br>     * 如果指定了时间, 则计算该固定时间点的下一时间点     */    private Period(int type, long interval, long offset, int times, Date date) {        // 参数检查        if(type != 0 && type != 1  && type != 2  && type != 3)            throw new IllegalArgumentException("type");        if(interval < 0)            throw new IllegalArgumentException("interval");        if(offset < 0)            throw new IllegalArgumentException("offset");        if(times < 0)            throw new IllegalArgumentException("times");                // 赋值        this.type = type;        this.interval = interval;        this.offset = offset;        this.times = times;        this.date = date;    }    /** 类型(0.DAILY|1.WEEKLY|2.MONTHLY|3.YEARLY) **/    public int getType() {        return type;    }    /** 间隔时间 **/    public long getInterval() {        return interval;    }    /** 偏移时间(从每个周期的什么时间开始) **/    public long getOffset() {        return offset;    }    /** 执行次数(每个周期的最大执行次数), 0表示无限制 **/    public int getTimes() {        return times;    }    /**     * 计算时的参照时间点<br>     * 如果为null, 每次计算时读取系统时间, 并计算其下一时间点<br>     * 如果指定了时间, 则计算该固定时间点的下一时间点     */    public Date getPoint() {        return date;    }    /**     * 移至某个计算所依据的时间点     * @param date 时间点     * @return     */    public Period toPoint(Date date) {        return new Period(type, interval, offset, times, date);    }    /**     * 移至下个间隔时间点, 并将该点作为计算所依据的时间点     * @return     */    public Period toNextTime() {        return new Period(type, interval, offset, times, getNextTime());    }    /**     * 获取周期的下一时间点     * @return     */    public Date getNextTime() {        Date date = this.date != null ? this.date : new Date();        return new Date(date.getTime() + getNextTimeOffset(date));    }    /**     * 获取到周期的下一时间点的毫秒数     * @return     */    public long getNextTimeOffset() {        return getNextTimeOffset(date != null ? date : new Date());    }    /**     * 获取到周期的下一时间点的毫秒数     * @param date 参照时间点     * @return     */    private long getNextTimeOffset(final Date date) {        log("------------------------------");        Calendar calendar = Calendar.getInstance();        calendar.setTime(date);        long result = 0L;        // 当前毫秒数        long current = calendar.getTimeInMillis();        log("当前时间: " + DateTools.dateToString(date));        // 本周期的开始时间的毫秒数        long period = getFirstTimeInPeriod(date);        log("本周期起点: " + DateTools.dateToString(new Date(period)));        // 起点, 本周期第一个时间点        long starting = period + offset;        log("第一个时间点: " + DateTools.dateToString(new Date(starting)));        if(current < starting) { // 小于起点            // 距起点的毫秒数            result = starting - current;        } else if(interval == 0L) {            result = 0L;        } else {            // 本周期已经过了的毫秒数, 相对于起点            long elapse = current - starting;            log("已消逝时间: " + DateTools.formatInterval(elapse));            // 本周期已经过了几个时间间隔            long count = elapse / interval + 1;            log("已消逝次数: " + count);            for(long i = 0; i < count && log; i++) {                if(i == 5 && count > 12) {                    log("...");                    i = count - 5;                }                long temp = starting + i * interval;                log((i + 1) + ". " + DateTools.dateToString(new Date(temp)));            }            // 下一时间点的毫秒数            long nextTime = starting + count * interval;            log("下一时间点: " + DateTools.dateToString(new Date(nextTime)));            // 下一周期的开始时间的毫秒数            long nextPeriod = getFirstTimeInPeriod(date, 1);            log("下一周期: " + DateTools.dateToString(new Date(nextPeriod)));            // 下一时间点在本周期内, 并且, 未超出本周期的次数限制            if(nextTime < nextPeriod && (times == 0 || count < times)) {                // 距下一时间点的毫秒数                result = nextTime - current;            } else {                // 距下一周期第一个时间点的毫秒数                result = nextPeriod + offset - current;            }        }        log("结果: " + DateTools.dateToString(new Date(current + result)));        return result;    }    /**     * 获取参照时间点所在的周期的开始时间点     * @param date 参照时间点     * @return     */    private long getFirstTimeInPeriod(final Date date) {        return getFirstTimeInPeriod(date, 0);    }    /**     * 获取参照时间点所在的周期的开始时间点     * @param date 参照时间点     * @param periodOffset 偏移几个周期<br>     * 如0表示当前周期, 1表示下一周期, -1表示上一周期, 类推     * @return     */    private long getFirstTimeInPeriod(final Date date, int periodOffset) {        Calendar calendar = Calendar.getInstance();        calendar.setTime(date);        switch(type) {        case DAILY:            if(periodOffset != 0) { // 周期偏移                periodOffset += calendar.get(Calendar.DAY_OF_MONTH);                calendar.set(Calendar.DAY_OF_MONTH, periodOffset);            }            break;        case WEEKLY:            if(periodOffset != 0) { // 周期偏移                periodOffset += calendar.get(Calendar.WEEK_OF_YEAR);                calendar.set(Calendar.WEEK_OF_YEAR, periodOffset);            }            // 日期置于周期起始位置            calendar.set(Calendar.DAY_OF_WEEK, 1);            break;        case MONTHLY:            if(periodOffset != 0) { // 周期偏移                periodOffset += calendar.get(Calendar.MONTH);                calendar.set(Calendar.MONTH, periodOffset);            }            // 日期置于周期起始位置            calendar.set(Calendar.DAY_OF_MONTH, 1);            break;        case YEARLY:            if(periodOffset != 0) { // 周期偏移                periodOffset += calendar.get(Calendar.YEAR);                calendar.set(Calendar.YEAR, periodOffset);            }            // 日期置于周期起始位置            calendar.set(Calendar.DAY_OF_YEAR, 1);            break;        }        // 时分秒置零        calendar.set(Calendar.HOUR_OF_DAY, 0);        calendar.set(Calendar.MINUTE, 0);        calendar.set(Calendar.SECOND, 0);        calendar.set(Calendar.MILLISECOND, 0);        return calendar.getTimeInMillis();    }    private void log(String msg) {        if(log) System.out.println(msg);    }    /**     * 每天执行一次的周期(时间单位为毫秒)     * @param offset 偏移时间(每天的什么时间执行)     * @return     */    public static Period getDailyOncePeriod(long offset) {        return MILLISECOND.getDailyOncePeriod(offset);    }    /**     * 每周执行一次的周期(时间单位为毫秒)     * @param offset 偏移时间(每周的什么时间执行)     * @return     */    public static Period getWeeklyOncePeriod(long offset) {        return MILLISECOND.getWeeklyOncePeriod(offset);    }    /**     * 每月执行一次的周期(时间单位为毫秒)     * @param offset 偏移时间(每月的什么时间执行)     * @return     */    public static Period getMonthlyOncePeriod(long offset) {        return MILLISECOND.getMonthlyOncePeriod(offset);    }    /**     * 每年执行一次的周期(时间单位为毫秒)     * @param offset 偏移时间(每年的什么时间执行)     * @return     */    public static Period getYearlyOncePeriod(long offset) {        return MILLISECOND.getYearlyOncePeriod(offset);    }    /**     * 每天的周期(时间单位为毫秒)     * @param interval 间隔时间     * @return     */    public static Period getDailyPeriod(long interval) {        return MILLISECOND.getDailyPeriod(interval);    }    /**     * 每天的周期(时间单位为毫秒)     * @param interval 间隔时间     * @param offset 偏移时间(每天的什么时间执行)     * @return     */    public static Period getDailyPeriod(long interval, long offset) {        return MILLISECOND.getDailyPeriod(interval, offset);    }    /**     * 每天的周期(时间单位为毫秒)     * @param interval 间隔时间     * @param offset 偏移时间(每天的什么时间执行)     * @param times 执行次数(每天的最大执行次数), 0表示无限制     * @return     */    public static Period getDailyPeriod(long interval, long offset,            int times) {        return MILLISECOND.getDailyPeriod(interval, offset, times);    }        /**     * 每周的周期(时间单位为毫秒)     * @param interval 间隔时间     * @return     */    public static Period getWeeklyPeriod(long interval) {        return MILLISECOND.getWeeklyPeriod(interval);    }    /**     * 每周的周期(时间单位为毫秒)     * @param interval 间隔时间     * @param offset 偏移时间(每周的什么时间执行)     * @return     */    public static Period getWeeklyPeriod(long interval, long offset) {        return MILLISECOND.getWeeklyPeriod(interval, offset);    }    /**     * 每周的周期(时间单位为毫秒)     * @param interval 间隔时间     * @param offset 偏移时间(每周的什么时间执行)     * @param times 执行次数(每周的最大执行次数), 0表示无限制     * @return     */    public static Period getWeeklyPeriod(long interval, long offset,            int times) {        return MILLISECOND.getWeeklyPeriod(interval, offset, times);    }    /**     * 每月的周期(时间单位为毫秒)     * @param interval 间隔时间     * @return     */    public static Period getMonthlyPeriod(long interval) {        return MILLISECOND.getMonthlyPeriod(interval);    }    /**     * 每月的周期(时间单位为毫秒)     * @param interval 间隔时间     * @param offset 偏移时间(每月的什么时间执行)     * @return     */    public static Period getMonthlyPeriod(long interval, long offset) {        return MILLISECOND.getMonthlyPeriod(interval, offset);    }    /**     * 每月的周期(时间单位为毫秒)     * @param interval 间隔时间     * @param offset 偏移时间(每月的什么时间执行)     * @param times 执行次数(每月的最大执行次数), 0表示无限制     * @return     */    public static Period getMonthlyPeriod(long interval, long offset,            int times) {        return MILLISECOND.getMonthlyPeriod(interval, offset, times);    }    /**     * 每年的周期(时间单位为毫秒)     * @param interval 间隔时间     * @return     */    public static Period getYearlyPeriod(long interval) {        return MILLISECOND.getYearlyPeriod(interval);    }    /**     * 每年的周期(时间单位为毫秒)     * @param interval 间隔时间     * @param offset 偏移时间(每年的什么时间执行)     * @return     */    public static Period getYearlyPeriod(long interval, long offset) {        return MILLISECOND.getYearlyPeriod(interval, offset);    }    /**     * 每年的周期(时间单位为毫秒)     * @param interval 间隔时间     * @param offset 偏移时间(每年的什么时间执行)     * @param times 执行次数(每年的最大执行次数), 0表示无限制     * @return     */    public static Period getYearlyPeriod(long interval, long offset,            int times) {        return MILLISECOND.getYearlyPeriod(interval, offset, times);    }    /**     * 时间单位<br>     * 如: Period.HOUR = 以小时作为时间单位<br>     * 该单位的所有方法的时间参数都以小时表示<br>     * Period.HOUR.getDailyPeriod(2); 表示每天隔2小时执行一次的周期<br>     * 已定义的时间单位有:<br>     * Period.DAY = 以天作为时间单位<br>     * Period.HOUR = 以小时作为时间单位<br>     * Period.MINUTE = 以分作为时间单位<br>     * Period.SECOND = 以秒作为时间单位<br>     * Period.MILLISECOND = 以毫秒作为时间单位<br>     */    public static class Unit {        /** 时间单位转换为毫秒的比率**/        private long rate;        /**         * 时间单位         * @param rate 时间单位转换为毫秒的比率         */        private Unit(long rate) {            this.rate = rate;        }        /**         * 每天执行一次的周期         * @param offset 偏移时间(每天的什么时间执行)         * @return         */        public Period getDailyOncePeriod(long offset) {            return new Period(DAILY, ONEDAY, offset * rate, 1, null);        }        /**         * 每周执行一次的周期         * @param offset 偏移时间(每周的什么时间执行)         * @return         */        public Period getWeeklyOncePeriod(long offset) {            return new Period(WEEKLY, 7 * ONEDAY, offset * rate, 1, null);        }        /**         * 每月执行一次的周期         * @param offset 偏移时间(每月的什么时间执行)         * @return         */        public Period getMonthlyOncePeriod(long offset) {            return new Period(MONTHLY, 28 * ONEDAY, offset * rate, 1, null);        }        /**         * 每年执行一次的周期         * @param offset 偏移时间(每年的什么时间执行)         * @return         */        public Period getYearlyOncePeriod(long offset) {            return new Period(YEARLY, 365 * ONEDAY, offset * rate, 1, null);        }        /**         * 每天的周期         * @param interval 间隔时间         * @return         */        public Period getDailyPeriod(long interval) {            return new Period(DAILY, interval * rate, 0, 0, null);        }        /**         * 每天的周期         * @param interval 间隔时间         * @param offset 偏移时间(每天的什么时间执行)         * @return         */        public Period getDailyPeriod(long interval, long offset) {            return new Period(DAILY, interval * rate, offset * rate, 0, null);        }        /**         * 每天的周期         * @param interval 间隔时间         * @param offset 偏移时间(每天的什么时间执行)         * @param times 执行次数(每天的最大执行次数), 0表示无限制         * @return         */        public Period getDailyPeriod(long interval, long offset, int times) {            return new Period(DAILY, interval*rate, offset*rate, times, null);        }                /**         * 每周的周期         * @param interval 间隔时间         * @return         */        public Period getWeeklyPeriod(long interval) {            return new Period(WEEKLY, interval * rate, 0, 0, null);        }        /**         * 每周的周期         * @param interval 间隔时间         * @param offset 偏移时间(每周的什么时间执行)         * @return         */        public Period getWeeklyPeriod(long interval, long offset) {            return new Period(WEEKLY, interval * rate, offset * rate, 0, null);        }        /**         * 每周的周期         * @param interval 间隔时间         * @param offset 偏移时间(每周的什么时间执行)         * @param times 执行次数(每周的最大执行次数), 0表示无限制         * @return         */        public Period getWeeklyPeriod(long interval, long offset, int times) {            return new Period(WEEKLY, interval*rate, offset*rate, times, null);        }            /**         * 每月的周期         * @param interval 间隔时间         * @return         */        public Period getMonthlyPeriod(long interval) {            return new Period(MONTHLY, interval * rate, 0, 0, null);        }        /**         * 每月的周期         * @param interval 间隔时间         * @param offset 偏移时间(每月的什么时间执行)         * @return         */        public Period getMonthlyPeriod(long interval, long offset) {            return new Period(MONTHLY, interval * rate, offset * rate, 0, null);        }        /**         * 每月的周期         * @param interval 间隔时间         * @param offset 偏移时间(每月的什么时间执行)         * @param times 执行次数(每月的最大执行次数), 0表示无限制         * @return         */        public Period getMonthlyPeriod(long interval, long offset, int times) {            return new Period(MONTHLY, interval*rate, offset*rate, times, null);        }            /**         * 每年的周期         * @param interval 间隔时间         * @return         */        public Period getYearlyPeriod(long interval) {            return new Period(YEARLY, interval * rate, 0, 0, null);        }        /**         * 每年的周期         * @param interval 间隔时间         * @param offset 偏移时间(每年的什么时间执行)         * @return         */        public Period getYearlyPeriod(long interval, long offset) {            return new Period(YEARLY, interval * rate, offset * rate, 0, null);        }        /**         * 每年的周期         * @param interval 间隔时间         * @param offset 偏移时间(每年的什么时间执行)         * @param times 执行次数(每年的最大执行次数), 0表示无限制         * @return         */        public Period getYearlyPeriod(long interval, long offset, int times) {            return new Period(YEARLY, interval*rate, offset*rate, times, null);        }    }    /** 测试 **/    public static void main(String[] args) {        Period.log = true;        System.out.println("每天, 间隔1小时30分钟, 2小时后开始, 次数无限制");        Period.MINUTE.getDailyPeriod(90, 2*60, 0)                .toPoint(DateTools.parseDate("2009-02-05 03:10:10.000"))                .toNextTime().toNextTime();        System.out.println(); System.out.println();        System.out.println("每天, 间隔1小时30分钟, 2小时后开始, 次数2");        Period.MINUTE.getDailyPeriod(90, 2*60, 2)                .toPoint(DateTools.parseDate("2009-02-05 03:10:10.000"))                .toNextTime().toNextTime();        System.out.println(); System.out.println();        System.out.println("每周, 间隔15小时, 26小时后开始, 次数无限制");        Period.HOUR.getWeeklyPeriod(15, 26, 0)                .toPoint(DateTools.parseDate("2009-02-07 22:00:00.000"))                .toNextTime().toNextTime();        System.out.println(); System.out.println();        System.out.println("每周, 间隔15小时, 26小时后开始, 次数无限制");        Period.HOUR.getWeeklyPeriod(15, 26, 0)                .toPoint(DateTools.parseDate("2009-02-05 10:10:10.000"))                .toNextTime().toNextTime();        System.out.println(); System.out.println();        System.out.println("每月, 间隔15小时, 26小时后开始, 次数无限制");        Period.HOUR.getMonthlyPeriod(15, 26, 0)                .toPoint(DateTools.parseDate("2009-02-28 23:00:00.000"))                .toNextTime().toNextTime();        System.out.println(); System.out.println();        System.out.println("每天5点执行一次");        Period.HOUR.getDailyOncePeriod(5)                .toPoint(DateTools.parseDate("2009-02-05 10:10:10.000"))                .toNextTime().toNextTime().toNextTime();        System.out.println(); System.out.println();        System.out.println("每隔5小时执行一次");        Period.HOUR.getYearlyPeriod(5)                .toPoint(DateTools.parseDate("2009-02-05 18:10:10.000"))                .toNextTime().toNextTime();        System.out.println(); System.out.println();        System.out.println("每周3的5点执行一次");        Period.HOUR.getWeeklyOncePeriod(3*24+5)                .toPoint(DateTools.parseDate("2009-02-05 10:10:10.000"))                .toNextTime().toNextTime().toNextTime();        Period.log = false;    }}


0 0
原创粉丝点击