( crontab: string )
| 103 | * - cronExpr:用于标准 cron 解析的表达式 |
| 104 | */ |
| 105 | export const extractCronExpr = ( |
| 106 | crontab: string |
| 107 | ): { |
| 108 | oncePos: number; |
| 109 | cronExpr: string; |
| 110 | } => { |
| 111 | const parts = crontab.trim().split(" "); |
| 112 | |
| 113 | /** |
| 114 | * 兼容 5 位 / 6 位 cron 表达式: |
| 115 | * - 5 位:分 时 日 月 周 |
| 116 | * - 6 位:秒 分 时 日 月 周 |
| 117 | */ |
| 118 | const lenOffset = parts.length === 5 ? 1 : 0; |
| 119 | |
| 120 | // 长度不合法,直接判定为非法表达式 |
| 121 | if (parts.length + lenOffset !== 6) { |
| 122 | throw new Error(t("cron_invalid_expr")); |
| 123 | } |
| 124 | |
| 125 | let oncePos = -1; |
| 126 | |
| 127 | for (let i = 0; i < parts.length; i++) { |
| 128 | const part = parts[i]; |
| 129 | if (part.startsWith("once")) { |
| 130 | // once 在 6 位 cron 中的真实位置 |
| 131 | // 5 位 cron 需要整体向后偏移一位 |
| 132 | oncePos = i + lenOffset; |
| 133 | parts[i] = part.slice(5, -1) || "*"; |
| 134 | break; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | return { cronExpr: parts.join(" "), oncePos }; |
| 139 | }; |
| 140 | |
| 141 | /** |
| 142 | * 解析 cron 表达式并计算下一次执行时间。 |
no test coverage detected