周期(实现了每天,每周,每月,每年的间隔一定时间重复执行的周期)
来源:互联网 发布: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
- 周期(实现了每天,每周,每月,每年的间隔一定时间重复执行的周期)
- [周期]根据当前时间计算每周星期几、每月几号、每年几月几日的执行时间
- 合格程序员的每天每周每月每年
- 合格程序员的每天每周每月每年
- 合格程序员的每天每周每月每年
- 获取与指定时间间隔一定周期的时间
- 合格程序员的每天每周每月每年(转帖)
- 程序员每天每周每月每年该做的事
- 合格程序员每天每周每月每年该做的
- 程序员每天每周每月每年该做的事
- 程序员每天每周每月每年该做的事
- 程序员每天、每周、每月和每年该做的事
- 程序员每天每周每月每年该做的事
- 程序员每天每周每月每年该做的事
- 程序员每天每周每月每年该做的事
- 合格程序员每天每周每月每年应该做的事
- 格程序员每天每周每月每年应该做的事
- 合格程序员每天每周每月每年应该做的事
- IAR调试cc2540 时 出现The stack plug-in failed to set a breakpoint on "main". 解决方法
- Vijos P1113 不高兴的津津
- Linux下获取目录下的文件列表,并按字符串排序
- Java经典算法整理 Part1
- 2013年蓝桥杯试题解析(一)
- 周期(实现了每天,每周,每月,每年的间隔一定时间重复执行的周期)
- 普通逻辑(00024考点)
- MyEclipse重命名JavaWeb项目
- Linux共享内存区参数设置
- 如何防止反复添加.h文件(头文件)
- NET 页面生命周期
- WhatsApp比微信好在哪里?
- jQuery验证控件jquery.validate.js使用说明+中文API(1)
- lzo安装说明