カレンダーに「立冬」と出る——表に名前を付けて渡す

Kairos

1. 暦の名前を、カレンダーに入れたい

衣替え、暖房の試運転、年賀状の準備。季節の節目を予定に入れておきたい人は多い。二十四節気はその目印で、立春・夏至・立冬・冬至の4 つくらいは、たいていの人が知っている。ところが、スマホのカレンダーに入れようとすると手が止まる。毎年日付が動くので、繰り返しの予定にできない。暦要項を見ながら 24 件を手で打つか、どこかのカレンダーを購読するか。

この回は、日付の表に名前を 1 行足すだけで、点を選ぶ・出す・渡すの 3 つの出口に同じ名前が出る話である。参照実装 1.0.12(10 月 26 日公開)で、出口に名前が出るようになった。言語は変わっていない。

2. 表に名前を付ける

2026 年の二十四節気は、国立天文台の暦要項に 24 の日付と時刻が載っている。日付だけを表にして、labels: で名前を並べる:

# 二十四節気
premise JP {
  calendar-system: Gregorian
  tz: "Asia/Tokyo"
  wkst: Mon
}

@JP
sekki = [2026-01-05, 2026-01-20, 2026-02-04, 2026-02-19, 2026-03-05, 2026-03-20,
         2026-04-05, 2026-04-20, 2026-05-05, 2026-05-21, 2026-06-06, 2026-06-21,
         2026-07-07, 2026-07-23, 2026-08-07, 2026-08-23, 2026-09-07, 2026-09-23,
         2026-10-08, 2026-10-23, 2026-11-07, 2026-11-22, 2026-12-07, 2026-12-22] covering: 2026..2026
  labels: [小寒, 大寒, 立春, 雨水, 啓蟄, 春分, 清明, 穀雨, 立夏, 小満, 芒種, 夏至,
           小暑, 大暑, 立秋, 処暑, 白露, 秋分, 寒露, 霜降, 立冬, 小雪, 大雪, 冬至]

sekki
  • sekki は 24 の日付の表。covering: 2026..2026 は「この表は 2026 年の分」という有効範囲の宣言(祝日表は黙って腐る)。
  • labels: は日付と同じ長さの名前の列。日付と名前が順に対応する。長さが違えばエラーで止まる。
  • 最後の sekki の 1 行が「出してほしい列」。表をそのまま出す。

11 月から年末までを聞く:

$ kairos list --from 2026-11-01 --to 2027-01-01 --tz Asia/Tokyo sekki.kairos
2026-11-07
2026-11-22
2026-12-07
2026-12-22
# 被覆サマリ
#   sekki covering 2026-01-01..2026-12-31 残走路 0 日

立冬・小雪・大雪・冬至の 4 日が出た。人間向けの表示に名前は出ない。点だけである。--to 2027-01-01 の日は含まない。この「右端を含まない」書き方は半開区間の回にある。

図 1: 2026 年 11 月の暦。10 月 26 日から 12 月 6 日までの 6 週を月曜始まりで並べ、11 月 7 日の立冬と 11 月 22 日の小雪のセルに二十四節気の名前を乗せる。11 月 3 日の文化の日と 11 月 23 日の勤労感謝の日は赤。下に、同じ 11 月 7 日の点が kairos list では日付だけ、--tsv では 8 列目の label に立冬、--ics では SUMMARY が「二十四節気 · 立冬」と出ることを 3 行で示す(2026-10-21 図を追加)
図 1: 2026 年 11 月の暦。10 月 26 日から 12 月 6 日までの 6 週を月曜始まりで並べ、11 月 7 日の立冬と 11 月 22 日の小雪のセルに二十四節気の名前を乗せる。11 月 3 日の文化の日と 11 月 23 日の勤労感謝の日は赤。下に、同じ 11 月 7 日の点が kairos list では日付だけ、–tsv では 8 列目の label に立冬、–ics では SUMMARY が「二十四節気 · 立冬」と出ることを 3 行で示す(2026-10-21 図を追加)

3. 名前で選ぶ

名前は表の中にあるので、名前で選べる。「冬至」だけを取る:

sekki |> filter(d => sekki(d) == 冬至)

sekki(d) は「点 d の名前を読む」という読み方で、表に名前を付けると自動で使えるようになる。序数(「22 番目」)ではなく名前で選ぶので、表の行が増えても式は変わらない。結果は 12/22 の 1 点。

4. 出口に名前が出る

ここが 1.0.12 で変わったところ。同じ sekki を、人に見せる以外の出口に出すと、名前が付いてくる。

TSV(Excel や DB へ渡す)は 8 列目に label が付く:

$ kairos list --tsv --from 2026-11-01 --to 2027-01-01 --tz Asia/Tokyo sekki.kairos
expr	source	uid	date	time	epoch_ms	note	label
1	sekki	kairos-66506f5e8d11-series@kairos-lang.org	2026-11-07		1793977200000		立冬
1	sekki	kairos-66506f5e8d11-series@kairos-lang.org	2026-11-22		1795273200000		小雪
1	sekki	kairos-66506f5e8d11-series@kairos-lang.org	2026-12-07		1796569200000		大雪
1	sekki	kairos-66506f5e8d11-series@kairos-lang.org	2026-12-22		1797865200000		冬至

7 列で読んでいた取り込みはそのまま動く。8 列目を読めば名前が取れる。

.ics(スマホのカレンダーへ)は、予定の題が「名前 · ラベル」になる:

$ kairos list --ics --from 2026-11-01 --to 2027-01-01 --tz Asia/Tokyo sekki.kairos > sekki.ics
BEGIN:VEVENT
DTSTART;VALUE=DATE:20261107
SUMMARY:二十四節気 · 立冬
DESCRIPTION:2026-11-07\nsekki

「二十四節気」はファイルの先頭のコメント行(# 二十四節気)から取られる。コメントが無ければ式の文字がそのまま題になる。取り込むと、11 月 7 日に「二十四節気 · 立冬」という終日の予定が入る。ラベルだけを題にしなかったのは、表によっては「12」「1」のような短いラベルがあり、それだけでは予定が読めないからである。

--ics は 1 点 1 予定の形で、点ごとに題が付けられる。--ics-series は 1 件の予定に日付を列挙する形なので、題は「二十四節気」の 1 つだけで、名前は付かない。取り込みの切り分け(UID・系列か個別か)は.ics 取り込みの事件簿にある。

--json を読むプログラムには results[].labels が増えた。dates と同じ長さの列で、名前の無い点は null。追加だけなので、既存の読み手はそのまま動く。MCP サーバも同じ報告を返す。

5. 名前が付かないとき

規則は 2 行で書ける。

  • 本体の式が参照する名前付きの表がちょうど 1 つのとき、各点にその表の名前を添える。
  • 表に無い点には名前が無い。参照が 0 個か、2 つ以上なら添えない。

「表に無い点」は、shift で動かした後に起きる。「節気の 3 日後」を出す:

sekki |> shift(+3, unit: day)

結果は 11/10・11/25・12/10・12/25 の 4 点で、label 列は空になる。11/10 は表にある日ではないので、名前が無い。これは正しい。「立冬の 3 日後」に「立冬」と書いてあったら、取り込んだカレンダーが嘘をつく。

「2 つ以上」は、節気の表と雑節の表を |(和)で 1 本の列にしたときに起きる。点ごとにどちらの表の名前かを決める規則を言語が持っていないので、添えない。label 列そのものが出ない。1 本の列に 2 つの表の名前を混ぜたいなら、式を 2 本に分けて、それぞれ出す。

六曜の回の「大安」は、表に書いた名前ではなく、朔のデータから計算した名前である。計算で付けた名前は、今の版では出口に出ない。出口に出るのは、表の行に書いた名前だけ。

6. 置き換えではない——上流の権威は上流に

  • 二十四節気の日付の正は、国立天文台が毎年 2 月に公表する暦要項にある。太陽の黄経で決まり、年によって日付が前後する(立春は 2 月 3 日の年も 4 日の年もある)。式が節気の日付を決めることはない。表は暦要項を写したもので、Kairos は表を読むだけである。
  • 暦を編む仕事の置き換えでもない。表の 24 行を書くのは人で、名前を付けるのも人。言語がするのは、名前を落とさずに出口まで運ぶことだけ。
  • 翌年分は、暦要項の 24 行を足して covering: を 2026..2027 にする。式は触らない。表が尽きた先を聞くと、点の代わりに「表の外」の註釈と残走路のマイナスが出る(前回)。

まとめ

  • 日付の表に labels: で名前を 1 行足す。式は sekki の 1 語
  • 名前で選べる(sekki(d) == 冬至)。序数で選ばない
  • 1.0.12 から、出口に名前が出る。TSV は 8 列目 label、.ics は題が「名前 · ラベル」、JSON は results[].labels
  • 名前が付くのは、式が参照する名前付きの表が 1 つのときだけ。動かした点・2 つの表の和・計算した名前には付かない
  • 日付の正は暦要項。式は表を読むだけで、決めない

▶ Playground で定義を実行する——11 月から年末までの 4 点が出る。最後の行を sekki |> filter(d => sekki(d) == 冬至) に替えると 12/22 だけになる。ブラウザ内で完結し、何も送信しない。


Kairos はスケジュール定義言語です——決めたら、いつでも。仕様と参照実装はGitHub で公開しています。

コメント

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