dsh-cron-toolkit
DeepSeek Harness 的 cron 表达式工具箱:explain_cron 中文解释,next_runs 推算运行时间(支持节假日黑名单),validate_cron 校验提示,cron_from_text 自然语言转表达式,infer_cron 由时间点反向推断。支持 5/6 段、Quartz L/W/#、英文缩写与 @daily 等宏。纯计算、零运行时依赖。
功能说明
面向 cron 表达式的"读懂 → 验证 → 排期 → 生成/反推"五个纯计算工具:
explain_cron —— 中文解释
逐字段翻译触发规则,并给出概要描述与规范化表达式:
表达式:*/15 9-18 * * 1-5
类型:5 段
字段解释:
分钟 */15 每 15 分钟
小时 9-18 9-18
日 * 每天
月 * 每月
星期 1-5 周一、周二、周三、周四、周五
概要:在 每天 / 周一、周二、周三、周四、周五 09:00,10:00,...,18:00 执行
规范:*/15 9-18 * * 1-5
next_runs —— 下次运行时间
表达式:0 9 * * 1-5
基准:2024-01-01T00:00:00.000Z(UTC)
时区:+08:00
1. 2024-01-01 09:00:00(周一) UTC 2024-01-01T01:00:00.000Z
2. 2024-01-02 09:00:00(周二) UTC 2024-01-02T01:00:00.000Z
validate_cron —— 校验与提示
给出合法性判定、规范化表达式与常见陷阱提示(如"日包含 31,短月不会触发")。
主要特性
- 5 段与 6 段:自动识别(
分 时 日 月 周 / 秒 分 时 日 月 周)
- 丰富语法:
*、?、a-b、a,b,c、*/n、a-b/n,月与星期支持 JAN/MON 等英文缩写
- 宏支持:
@yearly、@annually、@monthly、@weekly、@daily、@midnight、@hourly
- 星期日兼容:
0 与 7 均表示周日
- 日期语义:日与星期同时被限定时按 vixie-cron 规则取「或」
- Quartz 特殊记号(v0.2):日字段
L(月末最后一天,L-n 倒数)、LW(月末最后一个工作日);星期字段 5#3(第 3 个周五)、5L(最后一个周五)
- 节假日黑名单(v0.2):
next_runs 支持 skip_dates 跳过整天,支持单日与区间写法
- 双向能力(v0.2):
cron_from_text 自然语言 → 表达式(启发式),infer_cron 时间点样本 → 表达式
- 时区可配:
next_runs 支持 tz_offset(分钟),默认 +08:00
- 零 npm 依赖:仅使用 Node 内置模块
安装
npm install dsh-cron-toolkit
使用说明
explain_cron
用户:帮我看看 0 9 * * 1-5 是什么意思
表达式:0 9 * * 1-5
类型:5 段
字段解释:
分钟 0 第 0 分钟
小时 9 9
日 * 每天
月 * 每月
星期 1-5 周一、周二、周三、周四、周五
概要:(限 …)在 每天 / 周一、周二、周三、周四、周五 09:00 执行
规范:0 9 * * 1-5
参数:cron(表达式,5 段或 6 段,或 @daily 等宏)。
next_runs
用户:这个定时任务接下来 5 次什么时候跑
表达式:*/15 * * * *
基准:2024-01-01T00:00:00.000Z(UTC)
时区:+08:00
1. 2024-01-01 08:15:00(周一) UTC 2024-01-01T00:15:00.000Z
2. 2024-01-01 08:30:00(周一) UTC 2024-01-01T00:30:00.000Z
...
参数:cron、count(默认 5,上限 50)、from(基准时间,默认当前;结果为该时间之后)、tz_offset(分钟,默认 480)、skip_dates(v0.2:跳过日期,逗号/换行分隔的 YYYY-MM-DD 或区间 2024-10-01~2024-10-07,当天整体跳过)。
validate_cron
用户:0 0 31 * * 这个写法有问题吗
结果:✅ 合法
表达式:0 0 31 * *
段数:5
规范:0 0 31 * *
提示:
- 日包含 31,短月不会触发
参数:cron。
cron_from_text —— 自然语言转 cron(v0.2 新增)
把常见中文/混合描述转成 cron 表达式(启发式,仅供参考):
用户:每天上午 9 点跑一次,对应的 cron 是什么
text="每天上午 9 点"
文本:每天上午 9 点
表达式:0 9 * * *
概要:每天 09:00 执行
识别依据:
- 识别时刻 9:00(上午)
- 识别为每天
启发式结果,建议用 next_runs 核对触发时间。
支持写法:每 N 分钟/小时、每天、每周 X(周一/星期一/礼拜一)、每月 X 号、每月最后一天(→ L)、工作日、上午/下午/晚上 X 点(半)、9:30 时刻。参数:text(必填)。
infer_cron —— 时间点反向推断(v0.2 新增)
给出若干时间点(≥2),推断最可能的 cron 表达式并给出各字段依据:
用户:这四个时间点看起来像什么 cron
infer_cron(times="2024-01-01T00:00:00Z,2024-01-01T00:15:00Z,2024-01-01T00:30:00Z,2024-01-01T00:45:00Z")
样本:4 个时间点
推断表达式:*/15 0 1 1 1
字段依据:
分钟 */15 样本为 15 的整倍数序列
小时 0 全部样本一致
...
启发式推断(不支持 L/W/# 特殊记号),建议用 next_runs 与样本时间互验。
参数:times(必填,ISO 时间,逗号/换行分隔)、tz_offset(默认 480)。推断覆盖固定值/连续区间/步长/列表四种形态。
典型场景
1. 读懂别人的定时任务
用户:这个 cron 表达式是什么意思
explain_cron 一次给出逐字段解释与概要。
2. 排期核对
用户:这个任务下次什么时候执行
next_runs 列出接下来的运行时间(含星期与 UTC),便于与日历比对。
3. 上线前校验
用户:帮我确认这个表达式没写错
validate_cron 检查段数与取值范围,并提示短月、无解组合等陷阱。
4. 时区换算
用户:这个任务在美国东部时间几点跑
next_runs 传对应 tz_offset,同时给出墙钟时间与 UTC 时间。
5. 节假日不跑任务
用户:国庆假期这个任务不要跑
next_runs 传 skip_dates="2024-10-01~2024-10-07",整天跳过并顺延到假期后的第一个匹配时间。
6. 一句话生成 cron
用户:"每周一上午 9 点半"怎么写
cron_from_text 直接给出表达式与识别依据,再用 next_runs 验证。
7. 从历史触发时间反推表达式
用户:这个任务历史上都在每月 1 号跑,它的 cron 是什么
infer_cron 喂入若干触发时间点,推断最可能的表达式与各字段依据。
8. 无解表达式排查
用户:0 0 30 2 * 为什么一直不触发
next_runs 会明确报出"在未来 8 年内找不到匹配时间,表达式可能无解"。
安全边界
- 纯计算:五个工具均不读写文件、不访问网络、不修改系统计划任务;测试含确定性断言。
- 迭代与年限双上限:单次查找最多 20 万次迭代,且向后搜索不超过 8 年,超出即报错,避免无解表达式造成长时间占用。
- 显式报错:段数不符、取值越界、区间颠倒、未知宏等均抛出明确错误,不静默返回错误结果。
- 不做时区数据库下载:时区以分钟偏移表示,不依赖外部 tzdata。
- 只解释不执行:本插件只做表达式解析与时间推算,不会创建或修改任何定时任务。
其他插件集成说明
| dsh-plugin-timer | cron-toolkit 负责"解释与推算",plugin-timer 负责"到点执行/提醒" |
| dsh-date-calc | 用 format_date 把 next_runs 的结果做本地化展示;用 workdays_between 排除非工作日 |
| dsh-table-render | 把多次运行时间渲染成对齐表格 |
| dsh-workspace-journal | 把排期结果记录到工作区日志 |
| dsh-json-yaml-toolkit | 校验配置文件中的 cron 字段是否合法 |
版本说明
- 0.2.0(2026-10-17):按 RoadMap v0.2 迭代。
- Quartz 特殊记号:
L/L-n(月末/倒数)、LW(月末最后一个工作日)、d#n(第 n 个星期 d)、dL(最后一个星期 d),解释与推算均支持
next_runs 新增 skip_dates:节假日黑名单整天跳过,支持单日与区间(2024-10-01~2024-10-07)
- 新增
cron_from_text:自然语言 → cron(启发式,覆盖每 N 分钟/小时、每天/每周 X/每月 X 号/月末/工作日、上午下午晚上)
- 新增
infer_cron:若干时间点 → 最可能 cron(固定值/区间/步长/列表启发式,附字段依据)
- 0.1.0(2026-09-25):初始版本。
explain_cron:逐字段中文解释 + 概要 + 规范化
next_runs:N 次运行时间(时区可配、含星期与 UTC)
validate_cron:合法性校验 + 常见陷阱提示
- 5/6 段、宏、英文缩写、
7=周日、vixie-cron 日期取或语义
RoadMap
v0.2(已落地于 0.2.0)
- 支持 Quartz 风格的
L(月末)、W(最近工作日)、#(第 N 个星期几)
next_runs 支持跳过指定日期(节假日黑名单)
- 新增
cron_from_text:把"每天上午 9 点"这类自然语言转成表达式(启发式)
- 反向能力:给出若干时间点,推断最可能的 cron 表达式
v0.3(展望)
- 支持秒级
@every 30s 风格的间隔语法
- 输出 iCal RRULE 以便与日历系统对接
- 批量校验目录下所有配置文件中的 cron 字段
FAQ
Q:支持 5 段还是 6 段?
都支持。5 段为 分 时 日 月 周,6 段为 秒 分 时 日 月 周,工具会自动识别。
Q:星期日写 0 还是 7?
都表示周日,两者等价。
Q:日和周同时限定时怎么算?
按 vixie-cron 的经典规则:两者都被限定(非 *)时取「或」,只要满足其一即触发。validate_cron 会给出提示。Quartz 特殊记号(L/LW/#/dL)也按同一语义参与匹配。
Q:Quartz 的 L、W、# 支持到什么程度?
日字段支持 L(月末最后一天)、L-n(倒数第 n+1 天)、LW(月末最后一个工作日);星期字段支持 5#3(第 3 个周五)与 5L(最后一个周五)。注意 LW 的"工作日"按周一至周五计,不考虑法定节假日。
Q:cron_from_text 准不准?
它是启发式,覆盖常见中文写法,输出附带识别依据;复杂描述请先用它生成草稿,再用 next_runs 核对触发时间后使用。
Q:next_runs 的 from 是包含还是排除?
排除。返回的都是 from 之后的时间点。
Q:为什么有些表达式会报"无解"?
例如 0 0 30 2 *(2 月 30 日)永远不存在。插件会向后搜索 8 年,仍未命中即判定无解并报错。
Q:会不会真的创建定时任务?
不会。本插件只做解析与推算,执行请使用 dsh-plugin-timer。
源码与发布地址
许可证
MIT