From 90de9c7bd982406ddf776114ca4f47e2499b6fef Mon Sep 17 00:00:00 2001
From: lxyer <237809796@qq.com>
Date: Mon, 30 Jul 2018 13:55:18 +0800
Subject: [PATCH] .
---
.gitignore | 42 ++
pom.xml | 32 ++
src/main/java/com/lxyer/timer/Task.java | 497 ++++++++++++++++++
.../java/com/lxyer/timer/TimerExecutor.java | 126 +++++
src/test/java/com/lxyer/timer/TimerTest.java | 186 +++++++
src/test/java/package-info.java | 3 +
6 files changed, 886 insertions(+)
create mode 100644 .gitignore
create mode 100644 pom.xml
create mode 100644 src/main/java/com/lxyer/timer/Task.java
create mode 100644 src/main/java/com/lxyer/timer/TimerExecutor.java
create mode 100644 src/test/java/com/lxyer/timer/TimerTest.java
create mode 100644 src/test/java/package-info.java
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bb1a777
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,42 @@
+*.iml
+.idea/
+.ipr
+.iws
+*~
+~*
+*.diff
+*.patch
+*.bak
+.DS_Store
+Thumbs.db
+.svn/
+*.swp
+.nojekyll
+.project
+.settings/
+
+
+#==========================
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.war
+*.ear
+
+#=======================
+target
+.idea
+*.iml
+*.log
+logs
+*.iws
+*.classpath
+.DS_Store
+*.patch
+~$*
+
+*.MF
+tem
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..70c8456
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+ groupId
+ redtimer
+ 1.0-SNAPSHOT
+
+
+ junit
+ junit
+ 4.12
+ compile
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/lxyer/timer/Task.java b/src/main/java/com/lxyer/timer/Task.java
new file mode 100644
index 0000000..449b592
--- /dev/null
+++ b/src/main/java/com/lxyer/timer/Task.java
@@ -0,0 +1,497 @@
+package com.lxyer.timer;
+
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by liangxianyou at 2018/7/23 14:33.
+ */
+public abstract class Task implements Runnable {
+ protected String name;
+ protected long nextTime;
+ private TimerScheduled timerScheduled;
+ public abstract void run();
+
+ public Task(String name, String cfg){
+ this.name = name;
+ LocalDateTime now = LocalDateTime.now();
+ timerScheduled = new TimerScheduled(now.getYear(), now.getMonthValue(), cfg);
+ nextTime = timerScheduled.nextTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+ }
+
+ public long nextTime(){
+ LocalDateTime next = timerScheduled.nextTime();
+ this.nextTime = next.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+ return nextTime;
+ }
+}
+
+/**
+ * 时间解析器
+ */
+@SuppressWarnings("Duplicates")
+class TimerScheduled {
+ private int year;
+ private int month;
+ private int[] minutes;
+ private int[] hours;
+ private int[] days;
+ private int[] monthes;
+ private int[] weeks;
+ String[] cfgArr;
+
+ LocalDateTime nextTime;
+ private int _y,_M,_d,_H,_m;
+
+ public TimerScheduled(int year, int month, String cfg) {
+ this.year = year;
+ this.month = month;
+ this.cfgArr = cfg.split(" ");
+
+ setWeeks();
+ setMonthes();
+ setDays();
+ setHours();
+ setMinutes();
+
+ //寻找初始合法时间
+ LocalDateTime now = LocalDateTime.now();
+ _y = now.getYear();
+ _M= now.getMonthValue();
+ _d= now.getDayOfMonth();
+ _H= now.getHour();
+ _m= now.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);
+
+ if (_y == now.getYear() && _M == now.getMonthValue() && _d == now.getDayOfMonth()
+ && _H == now.getHour() && _m == now.getMinute()){
+ carry("m");
+ }
+
+ nextTime = LocalDateTime.of(_y, _M, _d, _H, _m);
+ System.out.println(cfg);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ System.out.println("init:"+ sdf.format(nextTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()));
+ }
+
+ /**
+ * 下一次执行的时间
+ * @return
+ */
+ protected LocalDateTime nextTime(){
+
+ String cmd = "m";
+ carry(cmd);
+ nextTime = LocalDateTime.of(year, month
+ , _d == -1? nextTime.getDayOfMonth() : _d
+ , _H == -1? nextTime.getHour() : _H
+ , _m == -1? nextTime.getMinute() : _m);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ System.out.println("下次执行:"+ sdf.format(nextTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()));
+ return nextTime;
+ }
+
+ /**
+ * 通过发送指令进行进位
+ * @param cmd 进位指令
+ */
+ private void 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 = "";
+ }
+ }
+
+ /**
+ * 得到初始合法时间的索引
+ * @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 -1;
+ 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);
+ }
+ }
+
+}
diff --git a/src/main/java/com/lxyer/timer/TimerExecutor.java b/src/main/java/com/lxyer/timer/TimerExecutor.java
new file mode 100644
index 0000000..7db4ee4
--- /dev/null
+++ b/src/main/java/com/lxyer/timer/TimerExecutor.java
@@ -0,0 +1,126 @@
+package com.lxyer.timer;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Created by liangxianyou at 2018/7/23 14:07.
+ */
+public class TimerExecutor {
+ private TimerQueue queue = new TimerQueue();
+ private ExecutorService executor;
+
+ /**
+ * 创建定时调度器
+ * @param n 调度线程数
+ */
+ public TimerExecutor(int n) {
+ executor = Executors.newFixedThreadPool(n);
+ }
+
+ public void add(Task task){
+ queue.put(task);
+ }
+ private void add(Task task, boolean upTime){
+ if (upTime) task.nextTime();
+ queue.put(task);
+ }
+
+ /**
+ * 启动定时调度
+ */
+ public void start() {
+ new Thread(()->{
+ while (true){
+ try{
+ Task take = null;
+ try {
+ take = queue.take();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ executor.execute(take);
+ add(take, true);
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+ }).start();
+ }
+}
+
+class TimerQueue{
+ Object lock = new Object();
+ Task[] queue = new Task[128];
+ Set names = new HashSet<>();
+ int size=0;
+
+ void put(Task task) {
+ remove(task.name);
+ synchronized (lock){
+ int inx = size;//目标坐标
+ while (inx > 0 && queue[inx-1].nextTime > task.nextTime ){
+ inx--;
+ }
+
+ if (queue.length == size+1)
+ queue = Arrays.copyOf(queue, size * 2);
+
+ for (int i = size+1; i > inx; i--) {
+ queue[i] = queue[i-1];
+ queue[i-1] = null;
+ }
+ queue[inx] = task;
+
+ size++;
+ names.add(task.name);
+ lock.notify();
+ }
+ }
+
+ Task take() throws InterruptedException {
+ synchronized (lock){
+ if (size == 0) lock.wait();
+
+ long currentTime = System.currentTimeMillis();
+ long nextTime = queue[0].nextTime;
+
+ if (currentTime >= nextTime){
+ Task task = queue[0];
+ for (int i = 0; i < size;i++) {
+ queue[i] = queue[i+1];
+ }
+ queue[size-1] = null;
+ size--;
+ return task;
+ }else {
+ lock.wait(nextTime - currentTime);
+ return take();
+ }
+ }
+ }
+
+ Task remove(String name){
+ synchronized (lock){
+ if(!names.contains(name)) return null;
+
+ Task take = null;
+ for (int i = 0; i < size-1; i++) {
+ if (name.equals(queue[i].name)){
+ take = queue[i];
+ while (i < size+1){
+ queue[i] = queue[i+1];
+ queue[i+1] = null;
+ }
+ names.remove(name);
+ break;
+ }
+ }
+ return take;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/lxyer/timer/TimerTest.java b/src/test/java/com/lxyer/timer/TimerTest.java
new file mode 100644
index 0000000..33e785f
--- /dev/null
+++ b/src/test/java/com/lxyer/timer/TimerTest.java
@@ -0,0 +1,186 @@
+package com.lxyer.timer;
+
+import org.junit.Test;
+
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+
+/**
+ * t2 测试定时器加入任务的调度管理
+ * t6 测试时间表达式配置校验
+ * 其他测试用例
+ * Created by liangxianyou at 2018/7/19 17:19.
+ */
+@SuppressWarnings("Duplicates")
+public class TimerTest {
+
+ /**
+ * 启动定时器测试,
+ */
+ @Test
+ public void t2(){
+ TimerExecutor timerExecutor = new TimerExecutor(1);
+
+ timerExecutor.add(new Task("a1", "1-40 * * * *") {
+ @Override
+ public void run() {
+ ThreadLocal local = new ThreadLocal<>();
+ SimpleDateFormat sdf = local.get();
+ if (sdf == null){
+ sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ }
+ System.out.printf("执行任务:%s now:%s, %n", name, sdf.format(System.currentTimeMillis()));
+ }
+ });
+
+ timerExecutor.start();
+
+ try {
+ Thread.sleep(1500_000000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 测试给配置的时间 加1分钟
+ */
+ @Test
+ public void t3(){
+
+ // MM-dd HH:mm:ss
+ //0 2 * * *
+ //0-59 0-23 1-31(L) 1-12 0-6
+
+ LocalDateTime now = LocalDateTime.now();
+ LocalDateTime start = LocalDateTime.now();
+ LocalDateTime next = null;
+
+ String str = "8 18 * 7,8 4";
+ String[] ss = str.split(" ");
+ for (String s : ss) System.out.println(s);
+ System.out.println("----------");
+ //Minute * 1,3 1-3 */5 3-15/5 5
+ String minute = ss[0];
+
+ if ("*".equals(minute)){//*
+ next = start.plusMinutes(1);
+ } else if (minute.matches("^[0-5]??[0-9]??$")){//n
+ next = LocalDateTime.of(start.getYear(),
+ start.getMonth(),
+ start.getDayOfMonth(),
+ start.getHour(),
+ Integer.parseInt(minute));
+ }else if (minute.matches("^[*]/[0-9]+$")){// */5
+ next = start.plusMinutes(Integer.parseInt(minute.replace("*/","")));
+ }else if (minute.matches("^([0-5]??[0-9]??,)+([0-5]??[0-9]??)? $")){//1,3
+ String[] minutes = minute.split(",");
+ int inx=0;
+ for (int i = 0; i < minutes.length-1; i++) {
+ if (start.getMinute() >= Integer.parseInt(minutes[i]) && start.getMinute()< Integer.parseInt(minutes[i+1])){
+ inx = i+1;
+ }
+ }
+ next = LocalDateTime.of(start.getYear(),
+ start.getMonth(),
+ start.getDayOfMonth(),
+ start.getHour(),
+ Integer.parseInt(minutes[inx]));
+ }else if (minute.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??$")){//1-3
+ int m = start.getMinute();
+ String[] split = minute.split("-");
+ int s = Integer.parseInt(split[0]);
+ int e = Integer.parseInt(split[1]);
+
+ if (m < s || m > e){
+ m = s;
+ }else{
+ m = (m+1) < 60 ? (m+1) : 0;
+ }
+ next = LocalDateTime.of(start.getYear(),
+ start.getMonth(),
+ start.getDayOfMonth(),
+ start.getHour(),
+ m);
+ }else if (minute.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??/[0-5]??[0-9]??$")){//3-18/5
+ //
+ }
+
+ System.out.println(next.getMinute());
+ }
+
+ /**
+ * 测试各种正则表达式的合法性
+ */
+ @Test
+ public void t4(){
+ //Pattern pattern = Pattern.compile();
+ //Minute * 1,3 1-3 */5 3-15/5
+
+ //System.out.println("05".matches("^[0-5]??[0-9]??$"));
+ //System.out.println("*/5".matches("^[*]/[0-9]+$"));
+ //System.out.println("1,5,10,59".matches("^([0-5]??[0-9]??,)+([0-5]??[0-9]??)?$"));
+ //System.out.println("1-3".matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??$"));
+ //System.out.println("3-18/5".matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??/[0-5]??[0-9]??$"));
+
+ String str = "01-05/5";// * 1,3 1-3 */5 3-15/5
+ System.out.println(str.matches("^[0-5]??[0-9]??$"));
+ System.out.println(str.matches("^[*]/[0-9]+$"));
+ System.out.println(str.matches("^([0-5]??[0-9]??,)+([0-5]??[0-9]??)?$"));
+ System.out.println(str.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??$"));
+ System.out.println(str.matches("^[0-5]??[0-9]??\\-[0-5]??[0-9]??/[0-5]??[0-9]??$"));
+
+ }
+
+ /**
+ * LocalDateTime的一些api测试
+ */
+ @Test
+ public void t5(){
+ //Minute * 1,3 1-3 */5 3-15/5
+ String cfg = "* * * * *";
+ LocalDateTime time = LocalDateTime.of(2018, 7, 18, 11, 11);
+
+ int minute = time.getMinute();
+ int hour = time.getHour();
+ int day = time.getDayOfMonth();
+ int month = time.getMonthValue();
+ int week = time.getDayOfWeek().getValue();
+
+ //checkCfg
+ //if (month)
+ System.out.println(week);
+ }
+
+ /**
+ * 测试配置的表达式
+ */
+ @Test
+ public void t6(){
+ //分 时 日 月 周
+ /*
+ 08 18 * 7,8 4
+ */
+ new Task("task1", "1 22-23 * * 7") {
+ @Override
+ public void run() {
+ System.out.println("----");
+ System.out.println(new SimpleDateFormat("0: yyyy-MM-dd HH:mm:ss").format(nextTime));
+ System.out.println(new SimpleDateFormat("1: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("2: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("3: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("4: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("5: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("6: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("7: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("8: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("9: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("10: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("11: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("12: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ System.out.println(new SimpleDateFormat("13: yyyy-MM-dd HH:mm:ss").format(nextTime()));
+ }
+ }.run();
+
+ }
+}
diff --git a/src/test/java/package-info.java b/src/test/java/package-info.java
new file mode 100644
index 0000000..023b180
--- /dev/null
+++ b/src/test/java/package-info.java
@@ -0,0 +1,3 @@
+/**
+ * Created by liangxianyou at 2018/7/30 0:25.
+ */
\ No newline at end of file