ADR-31: 位相と紀元を規定する(grid の整列既定・紀元 epoch:・stride 一族は from: 必須)
判断: リファレンス実装で顕在化した位相・紀元の未規定 3 点(F43/F44/F49)を次のように確定する。
- grid の位相:
grid(w)の刻み始めは、wが市民時の幅(d)なら在圏tz:の真夜中、 経過時間の幅(h/m/s)なら紀元(下記 2)に整列することを既定とし、anchor:(cycleと 同じ語)で上書きできる。day = chronos grid 1dは無指定で「TZ 真夜中区切りの暦日」になる。 - 紀元(epoch): span の窓序数
n・epochOrdinal(u, d)の起点となる紀元は、言語既定を 1970-01-01T00:00(在圏 tz) とし、原始的定義のメンバーepoch:で暦法ごとに上書きできる (火星暦など別基準の暦法が張れる)。epoch:は暦法に内在する値であり、利用側の前文には置けない。 序数は 0 起点(monthOf(m) = m mod 12が m=0=紀元月で成立する座標。「第 N」を答えるordinalInの 1 起点とは役割が違う——序数座標 vs 窓相対の第 N)。 - stride/strideBy の起点: 「前段の窓の起点から供給」を廃止し、起点(位相アンカー)は
from:で必ず明示する(無ければ静的エラー)。決定は stride(軸相対)・strideBy(軸絶対)の 一族両方に適用される。窓ごとに数え直す版はordinalInへの還元(ADR-27)が既にある。
背景: リファレンス実装(impl/)が動かすために独自に固定した未規定点の差し戻し。
(F43) span/stride は phase:/from: を持つのに grid だけ位相の口が無く、1d は真夜中と読めても
10d 等の一般幅では位相が結果を変える。(F44) 「紀元起点の序数」の紀元がどの時点か spec にも
stdlib(yearOf = 紀元年 + m div 12)にも無い。(F49) 窓が複数あるとき「前段の窓の起点」は多義で、
「最初の窓」と読むと評価範囲に依存し I7(純粋・遅延)と緊張する。
却下した案:
- (F43)
anchor:を宣言必須にする。真夜中以外のdayは事実上なく、day = chronos grid 1d anchor: …は冗長(ADR-16 の統治は「取り違えが危険な省略」に絞る)。整列既定のみ規定してanchor:を導入しない 案も、一般幅の位相が表現不能のままになるため採らない。 - (F44) 言語既定 1970 固定(宣言ノブなし)。別紀元を要する暦法(火星暦・和暦的紀元)が張れない。 暦学的紀元(0001-01-01 等)は実装が重く、紀元以前の負序数問題自体は残るため利得がない。
- (F49) 「紀元以後の最初の窓の起点」と規定して窓供給を残す案。純粋にはなるが、「直近の月初に位相を 合わせる」という書き手の直観とずれた結果を黙って出す。点ごとに属する窓の起点を取る案は実質 「窓ごとリセット」になり、ストライドの設計(リセットしない・ADR-11)と矛盾する。
帰結:
- spec §3.6(grid 行・
epoch:)・§4.7(起点規則と例)・§4.9(epochOrdinal の 0 起点)・§5.2/§5.3・ §5.6 EBNF(member-key にepoch)・stdlib/gregorian.md を更新。ordinalInの 1 起点は不変。 - 既存の式の意味は変わらない(未規定だった箇所の確定=追加規定)。唯一の破壊的変更は「窓からの stride 起点供給」の廃止だが、これは RC で確定した意味論ではなく §4.7 の未決部分の削除である。
- リファレンス実装は既定紀元のみ対応(
epoch:の別値・DST TZ は未対応と明記)。
改訂(2026-07-08・ADR-33/34): 三点を追補する。
- 既定整列「市民時幅=tz 真夜中」の一般化(ADR-33): 真夜中が存在しない・二度ある市民日(DST の
00:00 遷移)でも定まるよう、「各市民日の開始瞬間(その日付になる最初の瞬間)」に整列すると読む。
通常日は真夜中と一致し、意味は変わらない。紀元「1970-01-01T00:00(在圏 tz)」が隙間に落ちる TZ でも
同じ「最初の瞬間」規則で定まる。紀元は tz の写像の逆像=tz が違えば chronos 上の別の点であり、
epochOrdinal・span 序数は premise 相対の座標である(ADR-33 判断 7)。 - データ由来窓の序数(F60・ADR-34):
epochOrdinalの序数は場合分けで定める——窓列が紀元を 含む(またはそれ以前へ延びる)なら従来どおり紀元窓 = 0(それ以前の窓は負。改訂 3 の floor 除算がこれを支える)。窓列が紀元まで届かないデータ由来窓(segmentByの有限データ等)では 「存在する最初の窓 = 0」とする。 - 値式
div/modの負の被除数(F63):divは floor 除算・modは数学的剰余 (結果の符号は法に従う)と明文化する。紀元以前・位相補正で月序数が負になる式(FiscalのfiscalYearNo等)が trunc 実装で黙って 1 年ずれるのを防ぐ(リファレンス実装は floor で挙動固定済み)。
改訂 2(2026-07-09・F81/F83=ADR-41 と同時確定): 二点を追補する。
- 時刻付き
anchor:の市民幅グリッドの窓境界(F81): 市民時幅ndの grid に時刻付きanchor:を与えたとき、窓境界は「anchor の属する市民日から n 日ごとの各市民日で、anchor の 壁時計時刻(ラベル読み)を最初に読む瞬間」——(a) その時刻が存在しない市民日(DST の隙間)は 隙間明けの最初の瞬間(ADR-33 判断 4 の時刻版)、(b) 二度ある市民日(秋戻し)は最初の 出現、(c) 存在しない市民日(Pacific/Apia 2011-12-30 級)には目盛りを置かない(窓は存在する 市民日で数える)。窓幅は市民日と同じく伸縮する。「anchor 点からの経過時間タイル」の読みは 幅規約(1d=市民日・ADR-11/12)が既に排除している。注意(F87): リファレンス実装の従来 挙動は anchor の日内オフセットを経過 ms で計算しており、anchor が DST 切替日に落ちると全目盛りが 壁時計からずれていた(グリッドが anchor 自身を通らない)——本改訂はこの挙動の修正を含む (通常日 anchor は不変)。strideBy(w, from:)の時刻付き from: も同じ規定に従う(整列同一視の 維持)。市民日の開始点を anchor にした場合は日整列(オフセット 0)と読む——真夜中遷移 tz (America/Santiago 級=切替日の日開始が壁時計 01:00)で日付 anchor が「全日 01:00」にならない ための特例(ADR-33 判断 4 の「日の開始」と整合。実装検証で確定)。 shift(unit: 市民窓語)の窓内オフセットは経過時間で保存(F83・設計者裁定 2026-07-09): 着地=着地窓の開始+(元の点 − 元の窓の開始)。オフセットが着地窓の幅を超えれば次窓へ 掛かる(「必ず動かす」を守り、寄せるのは roll の係=ADR-21 の分担)。DST 切替日をまたぐと 壁時計が変わる([3/7T09:00] |> shift(+1, unit: day)→ NY で 3/8 10:00)——これは定義された 挙動であり、壁時計に貼り付く決まりは premise 層の宣言(実体の opens・時刻付き anchor の tick=ADR-41)が担うという役割分担の帰結(裁定の読み:「中身は chronos・読みは premise の 射影」〈ADR-33〉の下で、ずらす算術は chronos 側——射影を往復する算術〈壁時計保存〉は秋戻しの 日に射影が単射でないため点を併合し・往復可逆性を失い・真夜中遷移 tz で day 整列を壊す)。 経過窓語(unit: hour等)は従来どおり(ラベルが無いので同義)。挙動を固定する回帰テストを リファレンス実装に置く。但し書き: 往復可逆(+n → −n 恒等)は、オフセットが着地窓の幅を超えて 次窓へ掛かった点(25 時間日の 24 時間目など)では立たない(窓幅超過は「必ず動かす」の帰結として 定義された挙動——実装検証で確認)。