cron の「9」は、何も言っていない
毎朝 9 時のバッチを cron で書くと、こうなる:
0 9 * * * backup.sh
この「9」は何時のことだろうか。答えは「そのサーバーの OS に設定されたタイムゾーンの 9 時」——つまり、この 5 文字はスケジュールの意味の一部をサーバー任せにしている。
だから、こういう事故が起きる。国内のサーバーからクラウドへ移行したら、バッチが昼の 2 時前に走るようになった(クラウドの既定は UTC だった)。コンテナ化したら、イメージのベース OS のタイムゾーンで走るようになった。crontab は 1 文字も変わっていないのに、である。第 7 弾で「どこの 9 時?」という問いを書いたが、今日はその答えをコードの側に持たせる話をする。
premise——式の前に、前提を宣言する
Kairos では、スケジュールの式を書く前に、その式が立っている前提を宣言する。これをpremise(前提の束)と呼ぶ:
premise JP {
calendar-system: Gregorian
tz: "Asia/Tokyo"
wkst: Mon
}
@JP
everyInstant |> strideBy(1d, from: 2026-09-01T09:00)
読み下すと——「グレゴリオ暦で、東京の壁時計で、週は月曜始まり。その前提の下で、9/1 の9 時から毎日」。@JP から下の式は、この前提の袋の中で意味を持つ。9 時という時刻も、「1 日」という幅も、すべて JP の宣言から解釈される。式の意味を決める文脈が、サーバーの設定ではなく定義の一部になっている。
同じ式、違う premise——実測
premise だけを書き換えて、同じ式を評価してみる。表示を UTC に固定すると、違いがそのまま見える。まず東京:
2026-09-01 2026-09-02 2026-09-03
日付だけが並んだ——東京の朝 9 時は、UTC のちょうど 0 時だからだ(UTC 表示では日付の先頭に見える)。次に premise の tz: を "America/New_York" に変えただけの同じ式:
2026-09-01T13:00 2026-09-02T13:00 2026-09-03T13:00
UTC の 13 時。同じ「毎朝 9 時」という字面が、物理的には 13 時間離れた別の瞬間の列になった。どちらも正しい——違うのは前提であり、その前提が名前付きで definition に書いてあることが要点である。この定義ファイルをどこのサーバーに持っていっても、コンテナに入れても、意味は 1 ミリ秒も動かない。
tz: を書き換えて再評価すると、上の 13 時間差がその場で再現できる。
タイムゾーンだけではない——「週」も前提である
premise の袋に入っているのは tz だけではない。たとえば wkst(週の始まり)。「毎週の頭」を取る式を、週の始まりだけ変えて評価すると:
wkst: Mon —— 2026-09-07, 2026-09-14, 2026-09-21 (月曜の列) wkst: Sun —— 2026-09-06, 2026-09-13, 2026-09-20 (日曜の列)
「今週」がどこで切れるかは文化の取り決めであって、自明ではない(月曜始まりの国も日曜始まりの組織も、土曜始まりの業界もある)。取り違えると「週次レポートの集計範囲が 1 日ずれる」型の、静かで根深い事故になる——だから Kairos では wkst も宣言必須で、書いていない定義はエラーになる。デフォルトで沈黙するくらいなら、書けと言う言語である。
このほか、暦法そのもの(グレゴリオ暦か、会計暦か、旧暦か——第 10 弾の六曜はここが違う)や、祝日カレンダー(どの組織の営業日か——第 12 弾の実体)も、すべて premise の層に宣言する。式の層(いつ発火するか)と前提の層(その言葉が何を意味するか)の二層構造が、この言語の背骨である。
まとめ
- cron の「9」はサーバー任せの 9 時——移行・コンテナ化で意味が静かに変わる
- Kairos は式の前に premise(前提の束) を宣言する——tz・週の始まり・暦法・カレンダーが 名前付きで定義の一部になり、定義がどこへ運ばれても意味が不変になる
- 同じ「毎朝 9 時」でも、premise が違えば物理的に別の瞬間の列(実測で 13 時間差)
- 前提は書かなければエラー——暗黙の前提を、名前のある宣言に変えるのがこの層の仕事
「どこの 9 時か」(第 7 弾)、「誰の今日か」(第 11 弾)——この連載で繰り返してきた問いは、ぜんぶ premise の層への問いだった。次回は、この前提の袋を取り替えたり派生させたりする話——「本社の暦と、大阪支社の暦」をどう書き分けるかを書く予定。
Kairos は設計中のスケジュール定義言語です。仕様と参照実装はGitHub で公開しています。

コメント