Cron 表达式解析器 实时展示表达式的语义(“每天 3 点”等)和下次触发时间,支持 Linux(5 位)、Spring(6 位)、Quartz(7 位)三种格式自动识别。
五字段基础格式(Linux/crontab):* * * * *
| 位 | 字段 | 取值 |
|---|---|---|
| 1 | 分钟 | 0-59 |
| 2 | 小时 | 0-23 |
| 3 | 日 | 1-31 |
| 4 | 月 | 1-12 |
| 5 | 周 | 0-7(0 和 7 都是周日) |
6/7 字段扩展:Spring 在前面加”秒”字段得 6 位;Quartz 再加”年”(可选)得 7 位。
常用通配符:
* 任意值, 枚举(1,3,5)- 范围(9-17)/ 步长(如 */15 表示每 15 个单位触发)? 占位不关心(仅 Quartz、新版 Spring 的日/周字段)L 最后一天(仅 Quartz、Spring ≥5.3)# 第 N 个星期几(如 2#3 第 3 个周二,仅 Quartz)写表达式的套路:从右向左填(先决定”每周几 / 每月几号”,再填时分),或借助在线工具把中文需求直接翻译成表达式。需要秒级精度或”每月最后一天”等复杂规则时用 Spring/Quartz;简单日常调度 Linux crontab 够用。
每分钟一次。Linux crontab 五个字段分别是"分 时 日 月 周",最小粒度是分钟。没有秒字段,想每秒/每 10 秒执行,用 systemd timer、脚本里 `while sleep 10; do ... done`,或者改用 Spring/Quartz(支持 6 位秒级格式)。
字段数即可识别——5 位是 Linux/crontab(分时日月周),6 位是 Spring(秒 + 前 5 位),7 位是 Quartz(秒分时日月周年)。另一个信号:Quartz 要求日和周字段有且仅有一个是 `?`(表示"不关心"),这是它独有的语法。复制表达式前先看运行环境。
Linux cron 做不到——`0 0 28-31 * *` 会在 28/29/30/31 号都执行。Quartz 专门支持 `L`(Last):`0 0 0 L * ?` 就是每月最后一天 0 点。Linux 下只能在脚本里加判断:`[ $(date -d tomorrow +%d) = 01 ] && do_thing`,成立才执行。Spring 从 5.3 起也支持 `L`。
很多实现里两者都表示"按 5 的步长触发",例如分钟字段会在 0、5、10、15... 触发。区别主要在于不同引擎对写法的兼容度和官方示例习惯不完全一致。稳妥做法:优先按你所处环境的官方文档或工具示例来写,跨环境复制时重新校验一次。
最常见原因——时区:crond 默认用系统时区,容器里可能是 UTC;Spring `@Scheduled` 默认 JVM 时区;Quartz 可按 Job 单独设。解决:Linux 在 crontab 顶部加 `CRON_TZ=Asia/Shanghai`;JVM 启动加 `-Duser.timezone=Asia/Shanghai`。其次是夏令时切换日的偶发跳过/重复。
Linux cron 里两者是"或"关系——`0 0 1 * 1` 表示"每月 1 号 OR 每周一" 0 点都跑,容易出错;想"每月 1 号且是周一"需自己在脚本里判断。Quartz 要求两者中一个必须是 `?`(互斥),解决了这个歧义。Spring 从 5.3 起沿用 Quartz 的 `?` 规则。