package dev.zhub.timer.scheduled; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 时间解析器 * * @author: liangxianyou */ @SuppressWarnings("Duplicates") public class ScheduledExpres implements Scheduled { private int year; private int month; private int[] minutes; private int[] hours; private int[] days; private int[] monthes; private int[] weeks; private String cfg; private String[] cfgArr; private LocalDateTime theTime; private int _y, _M, _d, _H, _m; @Deprecated private ScheduledExpres(String cfg) { this.cfg = cfg; this.theTime = LocalDateTime.now(); initTheTime(); } @Deprecated private ScheduledExpres(final LocalDateTime startTime, String cfg) { LocalDateTime now = LocalDateTime.now(); this.theTime = now.isAfter(startTime) ? now : startTime; this.cfg = cfg; initTheTime(); } public static Scheduled of(String cfg) { return new ScheduledExpres(cfg); } public static Scheduled of(final LocalDateTime startTime, String cfg) { return new ScheduledExpres(startTime, cfg); } //寻找初始合法时间 public void initTheTime() { year = theTime.getYear(); month = theTime.getMonthValue(); cfgArr = cfg.split(" "); setWeeks(); setMonthes(); setDays(); setHours(); setMinutes(); _y = theTime.getYear(); _M = theTime.getMonthValue(); _d = theTime.getDayOfMonth(); _H = theTime.getHour(); _m = theTime.getMinute(); String cmd = "";//y M d H m if (days.length == 0) cmd = "M"; do { carry(cmd); int inx; if ((inx = nowOk(monthes, _M)) < 0) { cmd = "y"; continue; } _M = monthes[inx]; if ((inx = nowOk(days, _d)) < 0) { cmd = "M"; continue; } _d = days[inx]; if ((inx = nowOk(hours, _H)) < 0) { cmd = "d"; continue; } _H = hours[inx]; if ((inx = nowOk(minutes, _m)) < 0) { cmd = "H"; continue; } _m = minutes[inx]; break; } while (true); theTime = LocalDateTime.of(_y, _M, _d, _H, _m); LocalDateTime now = LocalDateTime.now(); while (theTime.isBefore(now)) { theTime = carry("m"); } } /** * 下一次执行的时间 * * @return */ @Override public LocalDateTime nextTime() { if (theTime.isAfter(LocalDateTime.now())) { return theTime; } return theTime = carry("m"); } @Override public LocalDateTime theTime() { return theTime; } /** * 通过发送指令进行进位 * * @param cmd 进位指令 */ private LocalDateTime carry(String cmd) { int inx; while (!"".equals(cmd)) { switch (cmd) { case "y": _y = this.year = ++_y; _M = this.month = monthes[0]; setDays(); if (days.length == 0) { cmd = "M"; continue; } _d = days[0]; _H = hours[0]; _m = minutes[0]; break; case "M": if (_M < monthes[0]) { _M = monthes[0]; break; } inx = Arrays.binarySearch(monthes, _M); if (inx < 0 || inx >= monthes.length - 1) { cmd = "y"; continue; } _M = this.month = monthes[inx + 1]; setDays(); if (days.length == 0) { cmd = "M"; continue; } _d = days[0]; _H = hours[0]; _m = minutes[0]; break; case "d": if (_d < days[0]) { _d = days[0]; break; } inx = Arrays.binarySearch(days, _d); if (inx < 0 || inx >= days.length - 1) { cmd = "M"; continue; } _d = days[inx + 1]; _H = hours[0]; _m = minutes[0]; break; case "H": if (_H < hours[0]) { _H = hours[0]; break; } inx = Arrays.binarySearch(hours, _H); if (inx < 0 || inx >= hours.length - 1) { cmd = "d"; continue; } _H = hours[inx + 1]; _m = minutes[0]; break; case "m": if (_m < minutes[0]) { _m = minutes[0]; break; } inx = Arrays.binarySearch(minutes, _m); if (inx < 0 || inx >= minutes.length - 1) { cmd = "H"; continue; } _m = minutes[inx + 1]; break; } cmd = ""; } return LocalDateTime.of(_y, _M, _d, _H, _m); } /** * 得到初始合法时间的索引 * * @param arr 合法时间序列 * @param n 初始选中值 * @return 合法时间的索引 */ private int nowOk(int[] arr, int n) { if (arr == null || arr.length == 0) return -1; if (arr[0] > n) return 0; if (arr[arr.length - 1] < n) return 0; if (arr[arr.length - 1] == n) return arr.length - 1; for (int i = 0; i < arr.length - 1; i++) { if ((arr[i] < n && arr[i + 1] > n) || arr[i] == n) { return i; } } return -1; } /** * 以下为 初始化合法时间 weeks,monthes,days,hour,minutes 序列 */ private void setMinutes() { String cfg = cfgArr[0]; if ("*".equals(cfg)) {//* minutes = new int[60]; for (int i = 0; i < 60; i++) { minutes[i] = i; } } else if (cfg.matches("^[0-5]??[0-9]??$")) {//n minutes = new int[1]; minutes[0] = Integer.parseInt(cfg); } else if (cfg.matches("^[*]/[0-9]+$")) {// */5 String[] strArr = cfg.split("/"); int p = Integer.parseInt(strArr[1]); minutes = new int[60 / p]; for (int i = 0; i < minutes.length; i++) { minutes[i] = i * p; } } else if (cfg.matches("^([0-5]??[0-9]??,)+([0-5]??[0-9]??)?$")) {//1,3 String[] strings = cfg.split(","); minutes = new int[strings.length]; for (int i = 0; i < strings.length; i++) { minutes[i] = Integer.parseInt(strings[i]); } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??$")) {//1-3 String[] split = cfg.split("-"); int s = Integer.parseInt(split[0]); int e = Integer.parseInt(split[1]); minutes = new int[e - s + 1]; for (int i = 0; i < minutes.length; i++) { minutes[i] = s + i; } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??/[0-5]??[0-9]??$")) {//3-18/5 String[] strArr = cfg.split("/"); String[] str2Arr = strArr[0].split("-"); int s = Integer.parseInt(str2Arr[0]); int e = Integer.parseInt(str2Arr[1]); int p = Integer.parseInt(strArr[1]); minutes = new int[(e - s) / p]; for (int i = 0; i < minutes.length; i++) { minutes[i] = s + i * p; } } } private void setHours() { String cfg = cfgArr[1]; if ("*".equals(cfg)) {//* hours = new int[24]; for (int i = 0; i < hours.length; i++) { hours[i] = i; } } else if (cfg.matches("^[0-5]??[0-9]??$")) {//n hours = new int[1]; hours[0] = Integer.parseInt(cfg); } else if (cfg.matches("^[*]/[0-9]+$")) {// */5 String[] strArr = cfg.split("/"); int p = Integer.parseInt(strArr[1]); hours = new int[24 / p]; for (int i = 0; i < hours.length; i++) { hours[i] = i * p; } } else if (cfg.matches("^([0-5]??[0-9]??,)+([0-5]??[0-9]??)?$")) {//1,3 String[] strArr = cfg.split(","); hours = new int[strArr.length]; for (int i = 0; i < strArr.length; i++) { hours[i] = Integer.parseInt(strArr[i]); } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??$")) {//1-3 String[] split = cfg.split("-"); int s = Integer.parseInt(split[0]); int e = Integer.parseInt(split[1]); hours = new int[e - s + 1]; for (int i = 0; i < hours.length; i++) { hours[i] = s + i; } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??/[0-5]??[0-9]??$")) {//3-18/5 String[] strArr = cfg.split("/"); String[] str2Arr = strArr[0].split("-"); int s = Integer.parseInt(str2Arr[0]); int e = Integer.parseInt(str2Arr[1]); int p = Integer.parseInt(strArr[1]); hours = new int[(e - s) / p]; for (int i = 0; i < hours.length; i++) { hours[i] = s + i * p; } } } private void setWeeks() { String cfg = cfgArr[4]; if ("*".equals(cfg)) {//* weeks = new int[7]; for (int i = 0; i < weeks.length; i++) { weeks[i] = i + 1; } } else if (cfg.matches("^[0-5]??[0-9]??$")) {//n weeks = new int[1]; weeks[0] = Integer.parseInt(cfg); } else if (cfg.matches("^[*]/[0-9]+$")) {// */5 String[] strArr = cfg.split("/"); int p = Integer.parseInt(strArr[1]); weeks = new int[7 / p]; for (int i = 0; i < weeks.length; i++) { weeks[i] = i * p; } } else if (cfg.matches("^([0-5]??[0-9]??,)+([0-5]??[0-9]??)?$")) {//1,3 String[] strArr = cfg.split(","); weeks = new int[strArr.length]; for (int i = 0; i < strArr.length; i++) { weeks[i] = Integer.parseInt(strArr[i]); } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??$")) {//1-3 String[] split = cfg.split("-"); int s = Integer.parseInt(split[0]); int e = Integer.parseInt(split[1]); weeks = new int[e - s + 1]; for (int i = 0; i < weeks.length; i++) { weeks[i] = s + i; } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??/[0-5]??[0-9]??$")) {//3-18/5 String[] strArr = cfg.split("/"); String[] str2Arr = strArr[0].split("-"); int s = Integer.parseInt(str2Arr[0]); int e = Integer.parseInt(str2Arr[1]); int p = Integer.parseInt(strArr[1]); weeks = new int[(e - s) / p]; for (int i = 0; i < weeks.length; i++) { weeks[i] = s + i * p; } } } private void setMonthes() { String cfg = cfgArr[3]; if ("*".equals(cfg)) {//* monthes = new int[12]; for (int i = 0; i < monthes.length; i++) { monthes[i] = i + 1; } } else if (cfg.matches("^[0-5]??[0-9]??$")) {//n monthes = new int[1]; monthes[0] = Integer.parseInt(cfg); } else if (cfg.matches("^[*]/[0-9]+$")) {// */5 String[] strArr = cfg.split("/"); int p = Integer.parseInt(strArr[1]); monthes = new int[12 / p]; for (int i = 0; i < monthes.length; i++) { monthes[i] = i * p; } } else if (cfg.matches("^([0-5]??[0-9]??,)+([0-5]??[0-9]??)?$")) {//1,3 String[] strArr = cfg.split(","); monthes = new int[strArr.length]; for (int i = 0; i < strArr.length; i++) { monthes[i] = Integer.parseInt(strArr[i]); } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??$")) {//1-3 String[] split = cfg.split("-"); int s = Integer.parseInt(split[0]); int e = Integer.parseInt(split[1]); monthes = new int[e - s + 1]; for (int i = 0; i < monthes.length; i++) { monthes[i] = s + i; } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??/[0-5]??[0-9]??$")) {//3-18/5 String[] strArr = cfg.split("/"); String[] str2Arr = strArr[0].split("-"); int s = Integer.parseInt(str2Arr[0]); int e = Integer.parseInt(str2Arr[1]); int p = Integer.parseInt(strArr[1]); monthes = new int[(e - s) / p]; for (int i = 0; i < monthes.length; i++) { monthes[i] = s + i * p; } } } private void setDays() { String cfg = cfgArr[2]; //当前月份总天数, LocalDate firstDay = LocalDate.of(year, month, 1); int lengthOfMonth = firstDay.lengthOfMonth(); if ("*".equals(cfg)) {//* days = new int[lengthOfMonth]; for (int i = 0; i < days.length; i++) { days[i] = i + 1; } } else if (cfg.matches("^[0-5]??[0-9]??$")) {//n days = new int[1]; days[0] = Integer.parseInt(cfg); } else if (cfg.matches("^[*]/[0-9]+$")) {// */5 String[] strArr = cfg.split("/"); int p = Integer.parseInt(strArr[1]); days = new int[lengthOfMonth / p]; for (int i = 0; i < days.length; i++) { days[i] = i * p; } } else if (cfg.matches("^([0-5]??[0-9]??,)+([0-5]??[0-9]??)?$")) {//1,3 String[] strArr = cfg.split(","); days = new int[strArr.length]; for (int i = 0; i < strArr.length; i++) { days[i] = Integer.parseInt(strArr[i]); } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??$")) {//1-3 String[] split = cfg.split("-"); int s = Integer.parseInt(split[0]); int e = Integer.parseInt(split[1]); days = new int[e - s + 1]; for (int i = 0; i < days.length; i++) { days[i] = s + i; } } else if (cfg.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??/[0-5]??[0-9]??$")) {//3-18/5 String[] strArr = cfg.split("/"); String[] str2Arr = strArr[0].split("-"); int s = Integer.parseInt(str2Arr[0]); int e = Integer.parseInt(str2Arr[1]); int p = Integer.parseInt(strArr[1]); days = new int[(e - s) / p]; for (int i = 0; i < days.length; i++) { days[i] = s + i * p; } } int firstWeek = firstDay.getDayOfWeek().getValue(); List allDay = new ArrayList<>(); for (int i = 0; i < days.length; i++) { //int week = 7 - Math.abs(i - firstWeek) % 7;//当前星期X int week; int d = days[i]; if (d + firstWeek <= 8) { week = firstWeek + d - 1; } else { week = (d - (8 - firstWeek)) % 7; if (week == 0) week = 7; } //System.out.printf("M:%s,d:%s,w:%s%n", month, d, week); if (Arrays.binarySearch(weeks, week) > -1) { allDay.add(d);//加入日期 } } days = new int[allDay.size()]; for (int i = 0; i < allDay.size(); i++) { days[i] = allDay.get(i); } } }