Appearance
Cron 表达式详解与实战
Cron 表达式是一种用于描述周期性执行时间的字符串,广泛应用于各种任务调度框架(如 Linux Crontab、Quartz、Hangfire、Spring Task 等)。通过简短的字符组合,它可以精确表达诸如“每周五下午两点”、“朝九晚五每半小时”等复杂的业务定时需求。
一、 语法结构
Cron 表达式通常以 5 到 7 个空格隔开,分为 6 或 7 个域。常见的两种标准格式:
- 六位标准(常见于多数现代调度框架,如 .NET Core / Spring):
秒 分 小时 日期 月份 星期 - 七位标准(包含年份):
秒 分 小时 日期 月份 星期 年份
各字段的允许值与特殊字符:
| 字段 | 允许值 | 允许的特殊字符 |
|---|---|---|
| 秒 (Seconds) | 0~59 的整数 | , - * / |
| 分 (Minutes) | 0~59 的整数 | , - * / |
| 小时 (Hours) | 0~23 的整数 | , - * / |
| 日期 (DayofMonth) | 1~31 的整数(需考虑当月天数) | , - * ? / L W C |
| 月份 (Month) | 1~12 或 JAN-DEC | , - * / |
| 星期 (DayofWeek) | 1~7 或 SUN-SAT(1=SUN) | , - * ? / L C # |
| 年 (Year) [可选] | 1970~2099 | , - * / |
二、 特殊字符图解
理解 Cron 的关键在于掌握以下特殊字符的用法:
*(所有值):表示匹配该域的任意值。例如在“分”域使用*,表示每分钟触发。?(不指定值):只能用于“日期”和“星期”域。因为日期和星期会相互影响,如果只关心某一个,另一个必须用?占位。例如“每月20号触发”,星期域必须填?。-(区间):表示一个范围。例如在“分”域使用5-20,表示第 5 到第 20 分钟内每分钟触发。/(增量):表示起始时间开始触发,然后每隔固定时间触发一次。例如在“分”域使用5/20,表示从第 5 分钟开始,每 20 分钟触发一次(即 5, 25, 45 分钟)。,(枚举):表示列出具体值。例如在“分”域使用5,20,表示在第 5 分和第 20 分触发。L(最后 Last):只能用于“日期”和“星期”域。- 在“日期”域:表示本月最后一天。
- 在“星期”域:表示本周最后一天(即周六 SAT)。如果在数字后跟
L,如6L,表示本月最后一个星期五(1=SUN, 6=FRI)。
W(工作日 Weekday):只能用于“日期”域。表示离指定日期最近的有效工作日(周一至周五)。如5W,如果 5 号是周六,则在最近的周五(4号)触发;如果是周日,则在周一(6号)触发。注意:寻找最近工作日不会跨月。LW(最后工作日):连用表示某个月的最后一个工作日。#(第几个星期几):只能用于“星期”域。格式为星期#第几个。例如4#2表示某月的第二个星期三(4=WED)。
三、 常见实战场景速查
1. 简单周期循环
0 * 14 * * ?每天下午 2:00 到 2:59 期间的每 1 分钟触发0 0/5 14 * * ?每天下午 2:00 到 2:55 期间的每 5 分钟触发0 0 12 * * ?每天中午 12:00 触发0 15 10 * * ?每天上午 10:15 触发
2. 工作时间场景
0 0 10,14,16 * * ?每天上午 10:00、下午 2:00、下午 4:00 触发0 0/30 9-17 * * ?朝九晚五工作时间内,每半小时触发0 15 10 ? * MON-FRI周一到周五每天上午 10:15 触发
3. 月度与月末场景
0 0 2 1 * ?每月的 1 日凌晨 2:00 触发0 15 10 15 * ?每月 15 日上午 10:15 触发0 15 10 L * ?每月最后一日的上午 10:15 触发0 15 10 ? * 6L每月的最后一个星期五上午 10:15 触发0 15 10 ? * 6#3每月的第三个星期五上午 10:15 触发
四、 避坑指南
- 区分 5 位和 6 位表达式
- Linux 系统的 Crontab 默认是 5 位(分 时 日 月 周),不支持秒。
- 大多数业务代码框架(如 Quartz、.NET Core 定时库)支持 6 位或 7 位,开头第一位是秒。
- 复制网上的表达式前,一定要先确认你使用的框架支持几位。
?和*在日期/星期上的冲突 如果指定了具体的日期(如每月 1 号),星期必须用?(如0 0 0 1 * ?)。如果星期用*,会被框架判定为语法错误或导致不可预期的多次触发。- 星期 1 是周日 在标准的 Cron 表达式中,
1 = SUN,2 = MON,依次类推直到7 = SAT。容易因为习惯把 1 当作周一导致调度错乱。
