「どこの 9 時」かを、コードはどう覚えているか——premise 入門

Kairos

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 ミリ秒も動かない。

▶ Playground で開く

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 で公開しています。

コメント

タイトルとURLをコピーしました