ADR-55: 時点どうしの順序比較と標準糖衣 since/before——点集合を日時で切り出す(1.1 の追加拡張)
判断: 値層の順序比較 < <= > >= の定義域を「数値どうし」から「数値どうし・時点どうし」へ広げ、
stdlib(Gregorian 公開語・at の隣)に糖衣 2 語を置く。
since(p) = s => s |> filter(t => t >= p) # p 以後(含む) = s ∩ [p, ∞)
before(p) = s => s |> filter(t => t < p) # p より前(含まず)= s ∩ (−∞, p)
発端は 90-open 3-8(需要 2 例=40-examples/11 §(n)・「締め切りまでの残り営業時間」)。受け皿の epochOrdinal 形は
書けるが読みづらく、単位の問いを生んでいた。確定 2026-10-19・本 ADR の起草 2026-10-21。実装は 1.1.0(ADR-54 と
束ねて一度に公開する。本 ADR の時点では未実装——候補設計は draft §1.35・経過の記録は
30-syntax/11・12)。
- 1.0 は不変=追加拡張。1.0 で合法だった式の意味は一つも変わらない。時点どうしの順序比較は 1.0 では評価 エラー(「数値ではない: point」)で、本 ADR はその形を定義するだけである。エラーだった形の合法化は 追加拡張に含める(先例 ADR-45=RC5 追補 7・ADR-48。90-open 冒頭の分類の定義に 1 句を足す)。文法・字句・ 既存の語は不変。糖衣は展開で消える(ADR-23/§4.8)。
- 順序は chronos 上の瞬間の全順序。等値
==の時点規則(§4.9)と同じ台。tz・暦法・粒度に依らない (リテラルは在圏 tz で時点に解決=ADR-33)。単位は持たない——単位の問いはepochOrdinalの床比較に 由来する人工物であった。補題: 目盛り上のリテラル p ではepochOrdinal(u, t) >= epochOrdinal(u, p) ⟺ t >= p(現行正準と外延同値)。食い違うのは目盛り外(14:30=床形は 14:00 を含む・瞬間形は 15:00 から)だけ。 - 型違いはエラー。時点と数値・ラベル・単独時刻
Thh:mm・ストリームは順序比較できない——等値エラー (1.0 追補 22)と同じ日本語の型名で両辺を見て診断し、単独時刻は ADR-51 の誘導へ、ラベルは ADR-54 のlabelOrdinalへ誘導する(現行の順序比較の経路は左辺の英語種別で止まる=1.0.10 の実測。新分岐で統一)。 単独時刻どうしの順序は定義しない(3-11 と同時に判断)。 - 境界は半開 [since, before)=評価範囲
[from, to)・isOpen・窓と同じ規約。since(2026-10-26)は在圏 tz の市民日の開始瞬間。日粒度の列に時刻付きリテラルを渡すと日の点は 00:00 なのでeveryDay |> before(2026-11-04T17:00)は 11-04 を含む——当日の扱いは日付を 1 日ずらす(評価範囲と同じ作法)。警告は足さない(粒度の静的知識を 要し、整列「なし」の入力で判定できない)。文書化のみ。 - 展開は filter に固定。糖衣は展開先の意味を継承する(ADR-51 判断 5)——整列・窓を保存(
within(month) |> since(p) |> firstが成立)、輸送行は filter 行(新しい範囲外を生まない)、整列「なし」の和にも掛かる。stride(1, from: p)展開は採らない(註釈が評価域の末尾まで膨張・終点の双対が無い)。 - ADR-34 判断 4(点±幅算術を導入しない)は不変。順序は算術ではない——新しい点を作らず、隣接窓参照の 抜け道にならず、幅規約も tz 依存算術も値層へ入らない。ADR-34 に改訂節で相互参照。
- 名は
since/before(英語の含意が境界と一致・named-arg キー・core 語・公開語と綴りが重ならない・ 全コーパスで 0 件)。「今」は式に埋めない——日単位の切り出しは評価範囲の分離が第一・時刻の切り出しだけsince/before・日時は引数や呼ぶ側で注入(ADR-52 判断 2 と同じ据え方)。 - 置き場は Gregorian 公開語(
atと同じ・新機構なし)。1.1 以降の新語は予約語(ADR-54 判断 8 と共通) ——利用側 top-level のsince/before束縛は誘導つき静的エラー。1.0 のat等が利用側束縛を黙って覆う 既存挙動は不変(1.0 で動いていたファイルを止めない)。 - 糖衣 2 語は受理拡大と同時に出す(需要 2 例の動機は読みやすさ)。1.0 文書への先行案内はしない
(stride 形は註釈が膨張し
beforeが無い。1.1 まで待つ)。
背景(1.0.10 の実走): t >= 2026-10-26T14:00 はエラー・t == … は通る・epochOrdinal 形は 51 点・利用側
糖衣 stride(1, from:) も 51 点。差 \ で作る before は整列「なし」の和で ADR-36 の静的エラー、窓付き入力では窓を
落とし後段 last が I4 エラー。stride 形は註釈が 09-25..10-05 へ膨張(filter 形は ..10-01・点は同一)。終点の双対は
1.0 核だけでは書けない——核の順序比較が唯一の言語側の判断点。
却下した案: epochOrdinal 単位形(since(hour, p) 級=単位が情報を持たず目盛り外で床の罠。瞬間グリッド
chronos grid 1s は資源の壁)/stride(1, from: p) 展開(註釈の膨張・双対なし。受理拡大を認めない場合の
since 限定の退路として記録)/差 \・coincides で作る before(整列なしで割れる・窓を落とす・無名テーブルの
被覆行が出る)/名 until(takeLast(n, until:) の点包含と同語で境界が反転)・from/to(named-arg と 2 役・
“to” は包含に読まれる)・after(厳密に後)・between(SQL の両端包含・片側が書けない)/core 語 2 つとして
追加(核の最小集合〈ADR-23〉を増やし輸送表・整列表の行が要る。糖衣で足りる)/stdlib 公開語全部の top-level
再定義を静的エラーにする(at・monthStart に遡り 1.0 で動いていたファイルが止まり得る)。
帰結(1.1.0 の実装時に貫通させる面。順序は 30-syntax/11 の「実装の順序」):
- spec: §3.5 比較の行に型の注記(数値どうし・時点どうし・混在はエラー)・§4.9「等値の型」を「等値・順序の型」に・
§4.8 に標準糖衣例 1 行と予約語の規約・§4.7「期間限定は評価範囲の分離が正道」に since/before の一文・§5.4 に
命名確定行(不採: until・from/to・after・between)・glossary §6.5 に
at行と同型の行。EBNF・輸送表・整列表は 不変(ADR README のチェックリスト 4 面)。入口の否定リスト(README 日英・spec §1.2)に「点と日時の比較が無い」 が残っていないか確認。en ミラーは同一コミット。 - impl:
evalBinの 4 case(数値/時点の分岐+診断・型名の統一)・gregorian.kairosに 2 行・witness・ Playground 再構築(例に「締め切りまでの残り営業時間」を 1 本)・MCP の同梱 reference 再バンドル。 - 文書:
reference/since.md・before.md日英(1 語 1 ファイル)・stdlib 日英・epochOrdinal/takeLast/strideの落とし穴・40-examples/11 §(n) を糖衣形に(epochOrdinal形は「単位を明示したいとき」)・ llms.txt の正準例に 1 行。90-open 3-8 は 91-closed へ。ADR-34/52 に改訂・相互参照の節(本 ADR の起草と同日)。 - 版と記録: 言語が変わるので 1.1.0(ADR-54 と同じ節「## 1.1(日付)」・状態行 4 入口・doc-consistency の
正規表現を 1.1 対応に)。検定は follow→verify→publish で同版に追従。ブログの既公開(第 35 弾=
epochOrdinal形)は遡らず、公開後に糖衣形の追補記事。供給側へは便で通知(旧形は合法のまま・任意採用)。
検証の案(1.1.0 の witness。変異試験の 3 系統で赤を実測してから数える): (a) 第 35 弾の epochOrdinal 形と
糖衣形の 51 点が一致(変異=境界反転で赤)(b) before の < を <= に変異→17:00 が出て赤 (c) 14:30 錨で 50 点・
先頭 15:00(変異=床比較で 51 点)(d) 評価 09-25..10-05 で註釈がちょうど ..10-01(変異=stride 展開で ..10-05)
(e) 整列「なし」の和に before が掛かる(変異=\ 展開で ADR-36 エラー)(f) within(month) |> since(p) |> first=
[10-15, 11-01] (g) t >= 5・since(T14:00)・weekday(d) >= Mon が誘導つきエラー(ラベルの誘導先は
labelOrdinal)(h) 既存の数値比較 doctest が全数緑 (i) 予約語(利用側 since 束縛が静的エラー)。
経緯: 90-open 3-8 に採録(記録のみ・2026-09-30 の整理)→需要 2 例目「締め切りまでの残り営業時間」(2026-10-12・
ブログ第 35 弾は epochOrdinal 形で起草)→糖衣の構想を記録(2026-10-15)→1.1 RC の設計材料として 3 観点×審査×
横断の整合を起こし(2026-10-18・30-syntax/11・12)→論点 S1〜S7・C1〜C8 を推奨案で確定(2026-10-19)→本 ADR
(2026-10-21)。
改訂 1(2026-10-24・レビュー所見 2 件)
- 予約語はラベル名にも使えない(判断 8 の拡張)。名前解決は premise の公開語がラベル語彙より先なので、1.0 で
before/sinceをcycleのラベル列やlabels:に使っていた定義は、1.1 では黙って意味が変わり別の文言のエラー(cycle は「ラベルは名前」・== beforeは型違い)に化けていた。束縛と同じ誘導つき静的エラー(改名)に揃える。ADR-54 判断 8 と共通。 since(p)/before(p)のpは呼び出し時に検査する。糖衣の展開filter(t => t >= p)は点が流れたときにしか比較を通らず、列が空だと単独時刻や型違いのpが黙って通っていた(文書は静的エラーと言っていた)。stdlib の定義そのものに限る(派生withの同名束縛は利用側の定義のまま=§4.8)。展開が filter である判断 5 は不変。