Crontab中文表達式解析
簡介
最近工作中在使用調度框架,經常和定時表達式打交道,並且有查看表達式中文解釋的需求,於是在網上搜集資料和自己進行一定的修改,寫了一個Crontab表達式解析的工具類
詳解
這個沒啥好解釋,看資料,自己試着動手寫寫,看看運行時間示例是否和自己想象的一樣,就差不多了
不多說,直接上代碼:
package com.ninetech.cloud.bw.rpa.util;
import org.springframework.scheduling.support.CronSequenceGenerator;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* crontab 工具類
*/
public class CrontabUtils {
/**
* 需要展示的表達式時間條數
*/
private final static int size = 10;
private static final String common = "*";
private static final String questionMark = "?";
private static final String hyphen = "-";
private static final String slash = "/";
private static final String comma = ",";
private static final String second = "秒";
private static final String minute = "分";
private static final String hour = "時";
private static final String day = "日";
private static final String week = "周";
private static final String month = "月";
public static String parse(String crontab) {
try {
StringBuilder result = new StringBuilder("表達式:").append(crontab).append("\n");
result.append(translateToChinese(crontab)).append("\n");
result.append("\n").append("表達式執行時間列表示例:").append("\n");
for (String exampleTime : examples(crontab)) {
result.append(exampleTime).append("\n");
}
return result.toString();
} catch (Exception e) {
return "無Crontab表達式";
}
}
private static List<String> examples(String crontab) {
final CronSequenceGenerator generator = new CronSequenceGenerator(crontab);
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
List<String> res = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
date = generator.next(date);
res.add(sdf.format(date));
}
return res;
}
public static String translateToChinese(String cronExp) {
String[] tmpCorns = cronExp.split(" ");
StringBuffer sBuffer = new StringBuffer();
if (tmpCorns.length != 6) {
throw new RuntimeException("請補全表達式,必須標准的cron表達式才能解析");
}
// 解析月
descMonth(tmpCorns[4], sBuffer);
// 解析周
descWeek(tmpCorns[5], sBuffer);
// 解析日
descDay(tmpCorns[3], sBuffer);
// 解析時
descHour(tmpCorns[2], sBuffer);
// 解析分
descMinute(tmpCorns[1], sBuffer);
// 解析秒
descSecond(tmpCorns[0], sBuffer);
return sBuffer.toString();
}
private static void descSecond(String s, StringBuffer sBuffer) {
desc(s, sBuffer, second);
}
private static void descMinute(String s, StringBuffer sBuffer) {
desc(s, sBuffer, minute);
}
private static void descHour(String s, StringBuffer sBuffer) {
desc(s, sBuffer, hour);
}
private static void descDay(String s, StringBuffer sBuffer) {
desc(s, sBuffer, day);
}
private static void descWeek(String s, StringBuffer sBuffer) {
desc(s, sBuffer, week);
}
private static void descMonth(String s, StringBuffer sBuffer) {
desc(s, sBuffer, month);
}
private static void desc(String s, StringBuffer sBuffer, String flag) {
if (s.equals("1/1")) {
s="*";
}
if (s.equals("0/0")) {
s="0";
}
if (common.equals(s)) {
if (flag.equals(week)) {
sBuffer.append("每").append(turnWeek(s));
} else {
sBuffer.append("每").append(flag);
}
return;
}
if (questionMark.equals(s)) {
return ;
}
if (s.contains(comma)) {
String[] arr = s.split(comma);
for (String value : arr) {
if (value.length() != 0) {
if (flag.equals(week)) {
sBuffer.append(turnWeek(value)).append("和");
} else {
sBuffer.append("第").append(value).append(flag).append("和");
}
}
}
sBuffer.deleteCharAt(sBuffer.length()-1);
sBuffer.append("的");
return;
}
if (s.contains(hyphen)) {
String[] arr = s.split(hyphen);
if (arr.length!=2) {
throw new RuntimeException("表達式錯誤"+s);
}
if (flag.equals(week)) {
sBuffer.append(turnWeek(arr[0])).append(turnWeek(arr[1]));
} else {
sBuffer.append("從第").append(arr[0]).append(flag).append("到第").append(arr[1]).append(flag);
}
return;
}
if (s.contains(slash)) {
String[] arr = s.split(slash);
if (arr.length!=2) {
throw new RuntimeException("表達式錯誤"+s);
}
if (arr[0].equals(arr[1])||arr[0].equals("0")) {
sBuffer.append("每").append(arr[1]).append(flag);
}else {
sBuffer.append("每").append(arr[1]).append(flag).append("的第").append(arr[0]).append(flag);
}
return;
}
if (flag.equals(week)) {
sBuffer.append("每").append(turnWeek(s));
} else {
sBuffer.append("第").append(s).append(flag);
}
}
private static String turnWeek(String week){
switch (week) {
case "0":
return"周天";
case "1":
return"周一";
case "2":
return"周二";
case "3":
return"周三";
case "4":
return"周四";
case "5":
return"周五";
case "6":
return"周六";
case "7":
return"周日";
default:
return null;
}
}
public static void main(String[] args) {
for (String s : parse("0/10 3/5 1-3 * 1 0").split("\n")) {
System.out.println(s);
}
}
}
執行的結果如下:
表達式:0/10 3/5 1-3 * 1 0
第1月每周天每日從第1時到第3時每5分的第3分每10秒
表達式執行時間列表示例:
2022-01-02 01:03:00
2022-01-02 01:03:10
2022-01-02 01:03:20
2022-01-02 01:03:30
2022-01-02 01:03:40
2022-01-02 01:03:50
2022-01-02 01:08:00
2022-01-02 01:08:10
2022-01-02 01:08:20
2022-01-02 01:08:30
