日本語 · English(未訳)

05 — 天文由来の暦法の横断検証(旧暦以外)

発端はレビューの問い(2026-07-08):「天文現象から導き出される暦法は旧暦に限らない。それらを Kairos で 表現するために足りないものは何か。仕様のどこかが決定的に食い違って表現できないのか」。

仮説: 旧暦(../../stdlib/kyureki.md)で確立した形——天文瞬間列(権威データ)→ snapTo(day)segmentBy → 射影で読む——が他の天文暦法にも延長できるなら、決定的な食い違いは無く、欠落は データ供給の運用面(既知の宿題)に集約されるはず。最も際どい一件(ヒンドゥー暦のティティ=代表点が 真夜中でない規約)を実行検証し、残りは机上で構造を同定する。

本ページの ```kairos ブロックは doctest(impl/test/doctest.test.ts)で実行検証される。

5.1 ヒンドゥー暦のティティ(実行検証・合成データ)

(1) 仕様+期待値: ティティ(tithi)は月と太陽の離角 12° ごとの「太陰日」。長さは約 19〜26 時間で 不規則(天文現象由来の瞬間列)。パンチャーンガの規約は「各市民日の日の出時点に進行中のティティが、 その日のティティ」。日の出を一度も含まないティティは欠日(kshaya——その番号の日が暦から飛ぶ)。 合成データ(日の出 06:51 固定・ティティ境界 7 点)で、ティティ 3 の日=1/3、ティティ 6=欠日を期待値とする。

(2) premise 定義+本体式:

# eval: 2026-01-01..2026-01-07
premise Astro = Gregorian with {
  tz: "Asia/Tokyo"
  source: "synthetic-ephemeris"      # 実運用は暦・天文台の告示(地点依存=出所に地点を含める)
  sunrises = [2026-01-01T06:51, 2026-01-02T06:51, 2026-01-03T06:51,
              2026-01-04T06:51, 2026-01-05T06:51, 2026-01-06T06:51]
  tithiB   = [2026-01-01T03:00, 2026-01-02T01:00, 2026-01-02T22:30, 2026-01-03T19:00,
              2026-01-04T14:30, 2026-01-05T09:00, 2026-01-06T02:30]
  tithiW   = sunrises |> segmentBy(tithiB, edges: drop, empties: keep,
                                   labels: [1, 2, 3, 4, 5, 6, 7])
}
premise Panchanga { calendar-system: Astro; tz: "Asia/Tokyo"; wkst: Mon }
@Panchanga
# 「ティティ 3 の日」=その市民日の日の出がティティ窓 3 に入る日
sunrises |> within(day) |> first |> filter(s => tithiW(s) == 3) |> snapTo(day)
#=> 2026-01-03
#~> 範囲外 2026-01-01..2026-01-02(Astro.sunrises covering 2026-01-01T06:51..2026-01-06T06:51)
#~> 範囲外 2026-01-06..2026-01-07(Astro.sunrises covering 2026-01-01T06:51..2026-01-06T06:51)
#~> 範囲外 2026-01-06..2026-01-07(Astro.tithiB covering 2026-01-01T03:00..2026-01-06T02:30)

欠日(kshaya)——ティティ 6 の窓(01-05T09:00〜01-06T02:30)はどの日の出も含まないので、 「ティティ 6 の日」はになる(期待値なし=空列。空は正当な値・ADR-15):

# eval: 2026-01-01..2026-01-07
premise Astro = Gregorian with {
  tz: "Asia/Tokyo"
  source: "synthetic-ephemeris"
  sunrises = [2026-01-01T06:51, 2026-01-02T06:51, 2026-01-03T06:51,
              2026-01-04T06:51, 2026-01-05T06:51, 2026-01-06T06:51]
  tithiB   = [2026-01-01T03:00, 2026-01-02T01:00, 2026-01-02T22:30, 2026-01-03T19:00,
              2026-01-04T14:30, 2026-01-05T09:00, 2026-01-06T02:30]
  tithiW   = sunrises |> segmentBy(tithiB, edges: drop, empties: keep,
                                   labels: [1, 2, 3, 4, 5, 6, 7])
}
premise Panchanga { calendar-system: Astro; tz: "Asia/Tokyo"; wkst: Mon }
@Panchanga
sunrises |> within(day) |> first |> filter(s => tithiW(s) == 6) |> snapTo(day)
#~> 範囲外 2026-01-01..2026-01-02(Astro.sunrises covering 2026-01-01T06:51..2026-01-06T06:51)
#~> 範囲外 2026-01-06..2026-01-07(Astro.sunrises covering 2026-01-01T06:51..2026-01-06T06:51)
#~> 範囲外 2026-01-06..2026-01-07(Astro.tithiB covering 2026-01-01T03:00..2026-01-06T02:30)

(3) core との差: 糖衣なし(すべて core と確定射影のみ)。

(4) 判定: 書ける(要外部データ=日の出・ティティ境界の瞬間列)。

(5) 綻びログ: 新しい綻びは出なかった。鍵は次の等価変形——「点→その日の日の出」という 点→点のデータ関数sunriseOf(d)。F28 で保留した持ち上げの一種)が要るように見えるが、 「窓ごとの代表点は選択子で取れる」(sunrises |> within(day) |> first)ので不要。ISO 週番号の F57(label: 不要の等価変形)と同じパターンで、F28 の保留(射影を先に・持ち上げは後回し)の 主要動機がまた一つ消えた。設計上の観察:

5.2 机上検証: 他の天文暦法の還元(構造の同定)

暦法 天文の核 Kairos での形 判定
イスラム暦(ウンム・アルクラー等の計算暦) 月初判定(メッカでの月没・朔条件) 月初日列=朔と同型 → segmentBy で月を切る(旧暦パターンそのまま) 書ける(要外部データ)
イスラム暦(観測ベース) ヒラール(新月の初視認)の観測で月初が確定 同上+確定が遅延到着する版付きデータ——asof: の版管理と、未確定域の範囲外出自(F61)が受け皿 書ける(F61 の活性化で運用が立つ)
バハーイー暦 テヘランの春分でナウルーズ(年初)が決まる segmentBy(equinoxes \|> snapTo(day)) で年を切る——春分データ(95-reference-data と同種)と同型 書ける(要外部データ)
ヘブライ暦・イスラム暦の「日没起点の日」 日は日没に始まる 日没瞬間列で segmentBy——§5.1 と同型の独自窓。tz 市民日(ADR-33)とは別の窓として立ち、衝突しない 書ける(要外部データ)
潮汐・天文薄明のスケジュール 満潮・薄明の瞬間そのもの 瞬間列テーブルがそのまま発報列(射影・窓も不要) 書ける(要外部データ)
火星暦(sol) 別スケールの均等日 strideBy(24h39m35.244s, from:)epoch:——ADR-19/31/33 で確定済み 書ける

5.3 まとめ——足りないものは何か

決定的な食い違いは無い。 天文暦法の共通構造(不規則な瞬間列が窓の切れ目を決める)は、 データ駆動の窓(ADR-26「暦法純粋 I8 が禁じるのはカレンダー依存であってデータ依存ではない」・ F13「規則とデータの境界は premise の中を走る」)が最初から狙っていた形であり、旧暦が要 NAOJ 暦要項で あるのは欠陥ではなく設計上の境界(権威の告示が正・真正性判定のスコープ外と同じ線引き)。 言語内で天文計算そのもの(黄経・朔・日の出の算出)を行う層は意図的に持たない——連続量の 閾値イベントは事前計算済みの瞬間列として持ち込む。

欠落はすべて既知の宿題に還元される(新 F 番号なし):

ADR-36(整列)との接続: 天文瞬間列は整列「なし」なので、日次列との結合には snapTo の明示が 強制される——F22 で旧暦の朔日規約に使った作法が、言語全体の統治に昇格した。