|
| 1 | +import { format } from './utils'; |
| 2 | +import SimpleTime from './SimpleTime'; |
| 3 | + |
| 4 | +/* |
| 5 | + * Cron表达式中内建的域对象,封装了域的操作方法 |
| 6 | + * 初始化时通过type初始化类型,对应的操作域操作方法如下: |
| 7 | + * setBase:接受一个参数,用于设置域基值 |
| 8 | + * inc:增量,接受一个参数incr,每隔incr时间 |
| 9 | + * any:任意时刻,即* |
| 10 | + * manual:接受参数str,手动输入,用于输入比较复杂的域值str |
| 11 | + * ask:问号,日域或星期域有一个必然是? |
| 12 | + * last:将当前域设置成按倒数,如果输入参数则为倒数第几天,如果不输入参数,按setBase的值计算 |
| 13 | + * nolast:删除last属性 |
| 14 | + * workDay:日域是否为工作日,如果输入参数则为第几个工作日,如果不输入参数,按setBase的值计算 |
| 15 | + * noWorkDay:删除工作日属性 |
| 16 | + * selectWeek:第几周的周几,接受两个参数,week代表第几周,weekDay代表星期几 |
| 17 | + * toDomainStr:返回此域的Cron表达式域字符串 |
| 18 | + */ |
| 19 | + |
| 20 | +class _Domain { |
| 21 | + constructor(arg, type) { |
| 22 | + this.type = type; |
| 23 | + this.base = arg || "0"; |
| 24 | + if (type == 'weekDay' || type == 'day' || type == 'month') { |
| 25 | + this.base = this.base == "0" ? 1 : this.base; |
| 26 | + } |
| 27 | + if (!arg) { |
| 28 | + this.anyType = true; |
| 29 | + return; |
| 30 | + } |
| 31 | + } |
| 32 | + setBase(baseStr) { |
| 33 | + this.base = baseStr; |
| 34 | + } |
| 35 | + inc(incr) { |
| 36 | + delete this.anyType; |
| 37 | + delete this.askType; |
| 38 | + delete this.manualType; |
| 39 | + this.incStep = incr; |
| 40 | + } |
| 41 | + any() { |
| 42 | + delete this.incStep; |
| 43 | + delete this.askType; |
| 44 | + delete this.manualType; |
| 45 | + this.anyType = true; |
| 46 | + } |
| 47 | + manual(str) { |
| 48 | + delete this.incStep; |
| 49 | + delete this.anyType; |
| 50 | + delete this.askType; |
| 51 | + this.manualType = true; |
| 52 | + this.manualStr = str; |
| 53 | + } |
| 54 | + ask() { |
| 55 | + delete this.anyType; |
| 56 | + delete this.incStep; |
| 57 | + delete this.manualType; |
| 58 | + this.askType = true; |
| 59 | + } |
| 60 | + last(num) { |
| 61 | + delete this.askType; |
| 62 | + delete this.anyType; |
| 63 | + if (typeof num != "undefined") { |
| 64 | + this.base = num + ""; |
| 65 | + } |
| 66 | + const newBase = (this.base.match(/[\d]+/) || [this.base][0]) + "L"; |
| 67 | + this.base = newBase == "1L" ? "L" : newBase; |
| 68 | + } |
| 69 | + nolast() { |
| 70 | + this.base = this.base.replace(/L$/, ""); |
| 71 | + } |
| 72 | + workDay(num) { |
| 73 | + delete this.askType; |
| 74 | + delete this.anyType; |
| 75 | + if (typeof num != "undefined") { |
| 76 | + this.base = num + ""; |
| 77 | + } |
| 78 | + this.base = (this.base.match(/[\d]+/) || [this.base][0]) + "W"; |
| 79 | + } |
| 80 | + noworkDay() { |
| 81 | + this.base = this.base.replace(/W$/, ""); |
| 82 | + } |
| 83 | + selectWeek(week, weekDay) { |
| 84 | + this.manual(week + "#" + weekDay); |
| 85 | + } |
| 86 | + toDomainStr() { |
| 87 | + if (this.anyType) { |
| 88 | + return "*"; |
| 89 | + } |
| 90 | + if (this.incStep) { |
| 91 | + return this.base + "/" + this.incStep; |
| 92 | + } |
| 93 | + if (this.manualType) { |
| 94 | + return this.manualStr; |
| 95 | + } |
| 96 | + if (this.askType) { |
| 97 | + return "?"; |
| 98 | + } |
| 99 | + return this.base; |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +/* |
| 104 | + * Cron表达式类对象 |
| 105 | + * 初始化时入参为时间字符串形如 |
| 106 | + * 1.yyyy-mm-dd hh:MM:ss |
| 107 | + * 2.yyyy-mm-dd |
| 108 | + * 3.hh:MM:ss |
| 109 | + * 内建7个域:year,weekDay,month,day,hour,minute,second |
| 110 | + * 可以通过Cron的实例对象.domain[域].方法(参数)访问指定域的指定方法 |
| 111 | + * 可以通过内建的set方法访问 |
| 112 | + * 内建方法: |
| 113 | + * set:可以通过Cron的实例对象.set('域','方法',参数1,[...,参数n])访问指定域的指定方法 |
| 114 | + * toCron:返回当前Cron表达式对象的Cron表达式串 |
| 115 | + * 注意: |
| 116 | + * 1.日期输入需要校验格式,内部没有校验格式 |
| 117 | + * 2.weekDay域中,初始化后为? |
| 118 | + * 3.设置day域时,weekDay域会自动转换为?,反之亦然 |
| 119 | + * 4.具体域方法见_Domain类的内建方法 |
| 120 | + */ |
| 121 | +class Cron { |
| 122 | + constructor(baseTime) { |
| 123 | + this.time = new SimpleTime(baseTime); |
| 124 | + this.domain = { |
| 125 | + hour: new _Domain(this.time.getHour(), "hour"), |
| 126 | + minute: new _Domain(this.time.getMinute(), "minute"), |
| 127 | + second: new _Domain(this.time.getSecond(), "second"), |
| 128 | + day: new _Domain(this.time.getDay(), "day"), |
| 129 | + month: new _Domain(this.time.getMonth(), "month"), |
| 130 | + weekDay: new _Domain(null, "weekDay"), |
| 131 | + year: new _Domain(this.time.getYear(), "year") |
| 132 | + } |
| 133 | + this.domain.weekDay.ask(); |
| 134 | + } |
| 135 | + toCron() { |
| 136 | + const domainAry = []; |
| 137 | + domainAry.push(format(this.domain['second'].toDomainStr())); |
| 138 | + domainAry.push(format(this.domain['minute'].toDomainStr())); |
| 139 | + domainAry.push(format(this.domain['hour'].toDomainStr())); |
| 140 | + domainAry.push(format(this.domain['day'].toDomainStr())); |
| 141 | + domainAry.push(format(this.domain['month'].toDomainStr())); |
| 142 | + domainAry.push(this.domain['weekDay'].toDomainStr()); |
| 143 | + domainAry.push(this.domain['year'].toDomainStr()); |
| 144 | + return domainAry.join(" "); |
| 145 | + } |
| 146 | + set(domain, operationType) { |
| 147 | + if (domain == "weekDay" && (operationType != "ask")) { |
| 148 | + this.domain['day']["ask"](); |
| 149 | + } else if (domain == "day" && (operationType != "ask")) { |
| 150 | + this.domain['weekDay']["ask"](); |
| 151 | + } |
| 152 | + const args = []; |
| 153 | + for (let i = 2; i < arguments.length; i++) { |
| 154 | + args.push(arguments[i]); |
| 155 | + } |
| 156 | + this.domain[domain][operationType].apply(this.domain[domain], args); |
| 157 | + } |
| 158 | + pack(input) { |
| 159 | + const lines = []; |
| 160 | + let line = [input[0]]; |
| 161 | + for (let i = 1; i < input.length; i++) { |
| 162 | + if (line.length == 0 || input[i] - 1 == line[line.length - 1]) { |
| 163 | + line.push(input[i]); |
| 164 | + } else { |
| 165 | + lines.push(line); |
| 166 | + line = [input[i]]; |
| 167 | + } |
| 168 | + } |
| 169 | + lines.push(line); |
| 170 | + for (let i = 0; i < lines.length; i++) { |
| 171 | + lines[i] = lines[i].length > 2 ? lines[i].shift() + "-" + lines[i].pop() : lines[i].join(","); |
| 172 | + } |
| 173 | + return lines.join(","); |
| 174 | + } |
| 175 | +} |
| 176 | + |
| 177 | +export default Cron; |
| 178 | + |
| 179 | + |
0 commit comments