Cron Parser 是一款僅在瀏覽器中運作的 cron 解析器替代方案,可驗證經典的五欄位 crontab 語法、展開其所接受的所有數字運算子,並以本地時間與 ISO UTC 時間戳兩種形式回傳下五個符合的瞬間時間。輸入內容永遠不會離開輸入所在的分頁,因此控制計費作業或備份的規則能保持私密。此解析器刻意只鎖定可攜的數字核心,而非涵蓋所有 cron 變體,這代表它會拒絕秒數欄位、年份欄位、@-暱稱、JAN 或 MON 之類的名稱、雜湊排程、月底語法,以及 Quartz 的問號。這種狹隘的範圍正是其重點:包括「日期」與「星期幾」之間有完整文件的 OR 行為在內,經典 cron 語意都會被精確重現,使輸出與 Vixie cron 及 Cronie 在正式環境中執行的結果一致。最終,這是一項可讓你信心十足地貼在真實 crontab 行程旁、作為驗證輔助的工具。

為什麼開發者會尋找 Cron Parser 替代方案
經典 cron 語法看起來很小,但一個欄位放錯位置,就可能把作業從每小時執行變成每天執行;而一個看似普通的日期規則,也可能觸發在錯誤的星期幾。參考文件位於 Cronie 的 crontab 手冊以及 Oracle Linux 的 cron 指南,多數團隊仰賴這些頁面,而不重新發明規則。痛點通常出現在三個常見地方。
第一,基於函式庫的解析器會增加執行階段依賴。為了取得一個小型驗證輔助而引入 cron-utils,每個觸及該規則的服務都要付出 Maven 或 npm 套件、類別載入器與授權審查的成本。一個與 crontab 檔案並存的瀏覽器解析器,則能徹底消除這項負擔。
第二,代管型驗證工具通常需要網路往返。它們可能會記錄運算式、對冗長查詢做速率限制,或在版本更新間悄悄更改文法。當該規則控制的是夜間計費作業或刪除任務時,你會希望驗證器連續兩次都執行完全相同的動作。
第三,平台排程器會夾帶擴充功能。Quartz 加入了秒數與問號;Kubernetes CronJobs 也加入相同的擴充;systemd 計時器則以 OnCalendar 語法整個取代原本格式;CI 服務再疊上自家巨集。在某處解析無誤的規則,到了別處可能被直接拒絕,而失敗通常不會大聲示警。Cron Parser 在可攜的數字核心上畫出一條嚴格界線,確保你所驗證的,正是經典 crond 將執行的內容。
Cron Parser 驗證與回傳的內容
契約內容精簡且透明。你給它一個恰好由五個以空白分隔欄位組成的字串,它會依序執行四件事:
- 將輸入切分為五個固定位置。
- 依據慣用範圍與可接受的運算子驗證每個 token。
- 正規化運算式,並寫出一行摘要,說明每個欄位所選取的內容。
- 列舉下五個符合的瞬間時間,分別以瀏覽器的本地時間與 ISO UTC 時間戳顯示。
負責尋找下次執行時間的引擎以 UTC 運作。它以整分鐘為單位向前掃描,依文件所述的 OR 語意套用「日期」與「星期幾」規則,並在找到五筆符合結果時立即停止。為避免格式錯誤或極度稀疏的輸入鎖住瀏覽器,設有安全上限:若在五年內找不到任何符合項目,掃描會停止並由解析器回報這個空檔。日曆有效性來自 JavaScript Date 物件,因此 31 日會自然跳過沒有 31 日的月份,而 2 月規則也會正確處理閏年。
這種確定性正是讓此工具適合作為驗證輔助的價值所在。在同一台機器上,相同的輸入會產生相同的五個時間戳,因此你可以將它與真實的 crontab 安裝或所選排程器的試跑結果比對。開啟 Cron Parser,貼上規則,在作業部署前先讀懂實際會發生什麼。
逐步驗證五欄位運算式
程序很短,因為工具本身就短,但每一步都有其道理。當你想驗證一個即將上線的規則時,請依下列順序操作。
- 依「分鐘、小時、日期、月份、星期幾」的順序撰寫運算式,共五個欄位,欄位之間以單一空格或 tab 分隔。
- 使用數值、星號、逗號分隔的清單、以連字號表示的包含範圍,或在萬用字元或範圍上使用正值的步進,例如 */15 或 10-50/20。
- 將運算式貼入 Cron Parser,閱讀正規化後的形式、各欄位摘要,以及瀏覽器本地時間與 ISO UTC 時間戳所顯示的下五個執行時間。
- 將這五個時間戳與實際執行該作業的排程器之文件和所設定的時區進行比對,只有在兩個檢視結果一致時,才部署該規則。
若解析器回傳的是聚焦的錯誤訊息而非排程,請先讀完訊息再進行編輯。錯誤訊息會指出違規的欄位、被拒絕的運算子或欄位數量錯誤,比自行猜測更快速。常見的拒絕情況包含遞減範圍、步進值為零、清單項目為空、數值超出欄位範圍,以及任何長度不是恰好五個欄位的運算式。
欄位範圍與可接受的運算子
數字核心精簡到可在一個畫面內顯示。每個欄位都有固定範圍,解析器遵循記錄於 crontab(5) 手冊的 Cronie 慣例。
| 欄位 | 可接受範圍 | 允許的運算子 |
|---|---|---|
| 分鐘 | 0-59 | *, ,, -, / |
| 小時 | 0-23 | *, ,, -, / |
| 日期 | 1-31 | *, ,, -, / |
| 月份 | 1-12 | *, ,, -, / |
| 星期幾 | 0-7(0 與 7 都會正規化為星期日) | *, ,, -, / |
有幾種組合值得再看一眼:
- 清單可混用個別數值與範圍,例如 0,15,30,45 用於每刻鐘觸發,或 8-12 代表四小時的時段。
- 萬用字元上的步進(例如 */10)會從欄位最小值開始,因此分鐘欄位中的 */10 會選取 0、10、20、30、40 與 50。
- 範圍上的步進(例如 10-50/20)會選取 10、30 與 50,因為步進是從範圍起點開始計算,而非從零起算。
- 星期幾欄位中的 0 與 7 都代表星期日。解析器會在內部將 7 正規化為 0,因此像 * * * * 7 這樣的排程會被視為與 * * * * 0 完全相同。
「日期」與「星期幾」如何交互作用
這兩個日期欄位是 crontab 中最容易咬人的部分,因為傳統 cron 使用的是 OR 語意而非 AND。當「日期」與「星期幾」皆受限(非萬用字元)時,只要其中一個欄位符合,該時間就算符合。當其中一個日期欄位為萬用字元時,僅由受限的欄位決定是否符合。
舉例來說,有個規則預定在每月 21 日的 09:00 以及每週一執行計費作業。天真的寫法 0 9 21 * 1 並不會這樣做。它會在每月 21 日的 09:00 以及 每個星期一執行,因為 OR 語意讓星期幾欄位能獨立觸發。若要限制為兩者的交集,必須將其中一個日期欄位設為 *,使另一個成為唯一限制條件。這點記載於 Oracle Linux cron 指南 及 crontab(5) 手冊中,Cron Parser 也忠實重現此行為。當你閱讀各欄位摘要時,預期會看到 OR 行為被明確標示,避免部署了一個會在你沒預期的星期一觸發的規則。
在日曆有效性方面也存在一個小陷阱。沒有 31 日的月份會自然跳過 31 日,2 月規則則會正確處理閏年。解析器並不會對這些跳過的情況提出警告,因為它們屬於正常的日曆行為,但對於稀疏的排程而言,這些跳過可能會以令人意外的方式改變連續符合項目之間的間隔。
為何引擎維持 UTC,而你的排程器未必
下次執行時間掃描器以 UTC 列舉分鐘,再將結果格式化顯示。這個選擇讓演算法在跨越日光節約時間邊界時仍維持確定性,因為從日曆運算的角度來看,掃描從未跨越時鐘變更。本地時間的瀏覽器顯示僅屬呈現細節,並非排程本身。
另一方面,你的排程器會依其設定檔、容器或平台預設所指定的時區執行。Cronie 與 Vixie cron 預設使用系統時區。Kubernetes CronJobs 預設使用 controller manager 的時區,除非設定 spec.timeZone。各家雲端排程器則各有差異。Cron Parser 的 UTC 輸出讓你能在公平的基礎上比較兩個系統;本地時間輸出則讓你能檢核使用者實際看到的鐘點。若在日光節約時間調整後,兩種檢視相差一小時,代表排程本身沒問題,而是排程器的時區並非你所假設的那個。此時應修正部署設定,而非修改運算式。
Cron Parser 的界線:僅支援經典語法
解析器的界線是刻意畫下的,當你將它與試圖涵蓋所有變體的函式庫比較時,這條界線至關重要。
| 輸入特性 | Cron Parser | 常見替代函式庫 |
|---|---|---|
| 五欄位數字核心 | 接受 | 通常接受 |
| 六或七個欄位(Quartz,含秒數或年份) | 拒絕 | 經常接受 |
| 月份名稱(JAN、FEB)與星期名稱(MON) | 拒絕 | 部分版本接受 |
| 特殊暱稱(@daily、@hourly) | 拒絕 | 經常接受 |
| 問號、L、W、#(Quartz 擴充) | 拒絕 | 支援 Quartz 的版本會接受 |
| 雜湊排程與隨機範圍 | 拒絕 | 少數支援 |
| 日期欄位的經典 OR 語意 | 套用 | 依函式庫而異 |
| 網路呼叫或運算式記錄 | 無 | 視代管環境而定 |
狹隘的範圍正是讓此工具能安心放進程式碼審查的原因。你貼上的同一個運算式,在任何開啟此頁面的機器上都會回傳相同的正規化形式與相同的五個執行時間,因為沒有任何資料離開瀏覽器。若你需要 Quartz 語法來搭配 Java 排程器,請改用具針對性的工具,而非讓五欄位解析器去猜測。
若想更深入了解驗證流程以及各欄位的摘要方式,Cron Parser Online:驗證運算式與下次執行時間 一文從不同角度介紹同一個工具,與本篇以替代方案為焦點的檢視角度相輔相成。
若你正在評估各項選擇,用於用戶端 CSS 的 Box Shadow Generator API 替代方案 一文對此有詳細說明。