java 构造 Quartz Cron 表达式
构造 Quartz Cron 表达式
Quartz Cron 表达式由 6 或 7 个字段组成,分别代表:
| 字段 | 允许值 | 允许的特殊字符 |
|---|---|---|
| 秒 | 0-59 | , - * / |
| 分 | 0-59 | , - * / |
| 时 | 0-23 | , - * / |
| 日 | 1-31 | , - * ? / L W C |
| 月 | 1-12 或 JAN-DEC | , - * / |
| 周几 | 1-7 或 SUN-SAT | , - * ? / L C # |
| 年(可选) |
- 关键说明和注意事项
- 在 Linux Crontab 中,0代表星期日,1代表星期一,2代表星期二,依此类推。
- 在 Quartz 中,1代表星期日,2代表星期一,3代表星期二,依此类推。这是最常见的混淆点!
- 参考: https://www.cnblogs.com/knqiufan/p/18952882
代码实现
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
* 构造 Quartz Cron 表达式
* Quartz Cron 表达式由 6 或 7 个字段组成,分别代表:
* <p>
* 字段 允许值 允许的特殊字符
* •秒 0-59 , - * /
* •分 0-59 , - * /
* •时 0-23 , - * /
* •日 1-31 , - * ? / L W C
* •月 1-12 或 JAN-DEC , - * /
* •周几 1-7 或 SUN-SAT , - * ? / L C #
* •年(可选)
* <p>
* 关键说明和注意事项
* 在 Linux Crontab 中,0代表星期日,1代表星期一,2代表星期二,依此类推。
* 在 Quartz 中,1代表星期日,2代表星期一,3代表星期二,依此类推。这是最常见的混淆点!
* 参考: https://www.cnblogs.com/knqiufan/p/18952882
*/
public class CronExpressionGenerator {
// 星期名称到Cron表达式数字的映射
private static final Map<String, Integer> DAY_OF_WEEK_MAP = new HashMap<>();
static {
DAY_OF_WEEK_MAP.put("周一", 2);
DAY_OF_WEEK_MAP.put("周二", 3);
DAY_OF_WEEK_MAP.put("周三", 4);
DAY_OF_WEEK_MAP.put("周四", 5);
DAY_OF_WEEK_MAP.put("周五", 6);
DAY_OF_WEEK_MAP.put("周六", 7);
DAY_OF_WEEK_MAP.put("周日", 1);
DAY_OF_WEEK_MAP.put("星期一", 2);
DAY_OF_WEEK_MAP.put("星期二", 3);
DAY_OF_WEEK_MAP.put("星期三", 4);
DAY_OF_WEEK_MAP.put("星期四", 5);
DAY_OF_WEEK_MAP.put("星期五", 6);
DAY_OF_WEEK_MAP.put("星期六", 7);
DAY_OF_WEEK_MAP.put("星期日", 1);
}
public static void main(String[] args) {
// scanner();
int choice = 3;
String time = "11:11";
String dayInput = "10";
//String dayInput = "10";
generateCronExpression(choice, dayInput, time);
}
public static String generateCronExpression(int choice, String dayInput, String time) {
String cronExpression = "";
switch (choice) {
case 1:
cronExpression = generateDailyCron(time);
break;
case 2:
cronExpression = generateWeeklyCron(dayInput, time);
break;
case 3:
cronExpression = generateMonthlyCron(dayInput, "y", time);
break;
default:
throw new IllegalArgumentException("无效的choice类型");
}
return cronExpression;
}
private static void scanner() {
Scanner scanner = new Scanner(System.in);
System.out.println("请选择定时类型:");
System.out.println("1. 按日执行");
System.out.println("2. 按周执行");
System.out.println("3. 按月执行");
int choice = scanner.nextInt();
scanner.nextLine(); // 消耗换行符
String cronExpression = "";
switch (choice) {
case 1:
cronExpression = scannerDailyCron(scanner);
break;
case 2:
cronExpression = scannerWeeklyCron(scanner);
break;
case 3:
cronExpression = scannerMonthlyCron(scanner);
break;
default:
System.out.println("无效选择");
return;
}
System.out.println("生成的Quartz Cron表达式: " + cronExpression);
scanner.close();
}
/**
* 生成按日执行的Cron表达式
*/
private static String scannerDailyCron(Scanner scanner) {
System.out.println("请输入执行时间 (格式: HH:mm,如 12:00):");
String time = scanner.nextLine();
return generateDailyCron(time);
}
/**
* 生成按日执行的Cron表达式
*/
private static String generateDailyCron(String time) {
String[] parts = splitTime(time);
int hour = Integer.parseInt(parts[0]);
int minute = Integer.parseInt(parts[1]);
validateTime(hour, minute);
// Cron格式: 秒 分 时 日 月 星期
return String.format("0 %d %d * * ?", minute, hour);
}
/**
* 生成按周执行的Cron表达式
*/
private static String scannerWeeklyCron(Scanner scanner) {
System.out.println("请输入星期几 (如: 周一):");
String dayOfWeekInput = scanner.nextLine();
System.out.println("请输入执行时间 (格式: HH:mm,如 02:00):");
String time = scanner.nextLine();
return generateWeeklyCron(dayOfWeekInput, time);
}
/**
* 生成按周执行的Cron表达式
*/
private static String generateWeeklyCron(String dayOfWeekInput, String time) {
String[] parts = splitTime(time);
int hour = Integer.parseInt(parts[0]);
int minute = Integer.parseInt(parts[1]);
validateTime(hour, minute);
Integer dayOfWeek = DAY_OF_WEEK_MAP.get(dayOfWeekInput);
if (dayOfWeek == null) {
throw new IllegalArgumentException("无效的星期输入");
}
// Cron格式: 秒 分 时 日 月 星期
return String.format("0 %d %d ? * %d", minute, hour, dayOfWeek);
}
/**
* 生成按月执行的Cron表达式
*/
private static String scannerMonthlyCron(Scanner scanner) {
System.out.println("请输入每月的第几天 (1-31),或输入 'L' 表示最后一天:");
String dayInput = scanner.nextLine().trim();
String response = "";
int dayOfMonth;
if (!"L".equalsIgnoreCase(dayInput)) {
try {
dayOfMonth = Integer.parseInt(dayInput);
if (dayOfMonth < 1 || dayOfMonth > 31) {
throw new IllegalArgumentException("日期必须在1-31之间");
}
// 对于29、30、31日,提示用户可能的问题
if (dayOfMonth >= 29) {
System.out.println("注意: 选择" + dayOfMonth + "日可能导致在某些月份(如2月)不执行任务。");
System.out.println("是否希望使用当月最后一天代替? (y/n)");
response = scanner.nextLine().trim();
}
} catch (NumberFormatException e) {
throw new IllegalArgumentException("请输入有效的数字(1-31)或'L'表示最后一天");
}
}
System.out.println("请输入执行时间 (格式: HH:mm,如 02:00):");
String time = scanner.nextLine();
return generateMonthlyCron(dayInput, response, time);
}
/**
* 生成按月执行的Cron表达式
*
* @param dayInput 请输入有效的数字(1-31)或'L'表示最后一天
* @param response 对于29、30、31日 是否进行转换为最后一天 'L'
* @param time 执行时间 HH:mm 格式
*/
private static String generateMonthlyCron(String dayInput, String response, String time) {
boolean useLastDay = false;
int dayOfMonth = 1;
if ("L".equalsIgnoreCase(dayInput)) {
useLastDay = true;
} else {
try {
dayOfMonth = Integer.parseInt(dayInput);
if (dayOfMonth < 1 || dayOfMonth > 31) {
throw new IllegalArgumentException("日期必须在1-31之间");
}
// 对于29、30、31日,提示用户可能的问题
if (dayOfMonth >= 29) {
if ("y".equalsIgnoreCase(response) || "是".equalsIgnoreCase(response)) {
useLastDay = true;
}
}
} catch (NumberFormatException e) {
throw new IllegalArgumentException("请输入有效的数字(1-31)或'L'表示最后一天");
}
}
String[] parts = splitTime(time);
int hour = Integer.parseInt(parts[0]);
int minute = Integer.parseInt(parts[1]);
validateTime(hour, minute);
// Cron格式: 秒 分 时 日 月 星期
if (useLastDay) {
return String.format("0 %d %d L * ?", minute, hour);
} else {
return String.format("0 %d %d %d * ?", minute, hour, dayOfMonth);
}
}
private static String[] splitTime(String time) {
String[] parts = time.split(":");
if (parts.length != 2) {
throw new IllegalArgumentException("时间格式不正确,请使用 HH:mm 格式");
}
return parts;
}
/**
* 验证时间格式是否正确
*/
private static void validateTime(int hour, int minute) {
if (hour < 0 || hour > 23) {
throw new IllegalArgumentException("小时必须在0-23之间");
}
if (minute < 0 || minute > 59) {
throw new IllegalArgumentException("分钟必须在0-59之间");
}
}
}
3237

被折叠的 条评论
为什么被折叠?



