日本語 · English

標準 premise: Fiscal

Fiscal は Kairos に同梱される透明な標準 premise(会計暦・4 月始まり)。Gregorian を土台にした派生的定義(premise → premise。../spec/20-premise-layer.md §3.7)であり、原始的定義の根ではない。

1. 完全定義

premise Fiscal = Gregorian with {
  year = month span (_ => 12) phase: 3 label: (p => yearNo(p))   # 暦月を 4 月始まりで 12 ずつ束ね直す
                                                            # (ラベル=開始暦年=年度番号。上書きはラベルを
                                                            #   継承しない——同時付与が統治。ADR-42/F96)

  fiscalYearNo  = d => yearOf(epochOrdinal(month, d) - 3)   # 年度番号(開始暦年の規約。「2026 年度」= 2026)
  fiscalMonthNo = d => ordinalIn(month, year, d)            # 会計月番号(4 月 = 1 … 3 月 = 12)
}

上書きは year の一行である。span の窓序数は紀元——言語既定の 1970-01-01T00:00(在圏 tz)・0 起点 (ADR-31)——から数えるので、phase: 3 は「束ね始めを月序数 3(= 1970 年 4 月)に置く」の意。以降の切れ目は 毎年 4 月 1 日になる。残る二語は読み取り用の値関数(追加語)。右辺の yearOf は Gregorian の公開束縛 (gregorian.md §1 の完全定義に含まれる補助値関数)を裸名で参照し、epochOrdinal・ ordinalIn は言語の射影一族の記述語である(ADR-27)。

この定義は同梱ソース ../impl/stdlib/fiscal.kairos そのものであり、前文で calendar-system: Fiscal と書けば宣言なしで使える。year の上書きだけなら、糖衣 rephase(正式名=2026-07-26 決定・旧仮称 shiftBoundary)でも書ける:

premise Fiscal = Gregorian |> rephase(+3, on: year, unit: month)   # year 一行と同じ展開

# 展開規則: rephase(δ, on: W, unit: U)  ≡  W = U span (_ => k) phase: ((φ₀ + δ) mod k)
#   (負の δ も法で正規化=F65。base の label: は保存=F96——§1 の label: 同時付与と等価が立つ根拠)
#   ここでは k = 12(year ⊃ month の個数)・φ₀ = 0(Gregorian の year の位相)・δ = +3

2. 各語(何が変わり・何が変わらないか)

語 種別 説明
year 窓(上書き) 暦月を 4 月始まりで 12 ずつ束ね直す(phase: 3)。切れ目は毎年 4/1。標準ラベル=開始暦年(year(2026)=2026 年度の日々・ADR-42)。
fiscalYearNo 値関数(追加) 点の年度番号。開始暦年の規約(「2026 年度」= 2026。§5)。
fiscalMonthNo 値関数(追加) 会計月番号 1..12(4 月 = 1 … 3 月 = 12)。ordinalIn の再利用。
quarter 窓(継承・自動追従) 継承定義 year split (_ => [3, 3, 3, 3]) by: month が新 year に追従し、会計四半期(Apr–Jun/Jul–Sep/Oct–Dec/Jan–Mar)になる(§3)。
yearStart 公開境界語(継承・自動追従) 継承定義 year |> first が新 year に追従 → 4 月 1 日群。
day / month / week / weekday 窓・ラベル(継承・不動) 暦日・暦月・週・曜日は Gregorian のまま(§4)。
monthStart / monthEnd 公開境界語(継承・不動) 暦月の月初・月末。年度の切れ目に影響されない(§4)。
yearNo / monthNo / dayNo 値関数(継承・不動) 暦座標の糖衣(gregorian.md §2)。定義が year 窓でなく month 序数を参照するため追従しない——yearNo は暦年であって年度ではない(年度は fiscalYearNo)。

各会計年度の初日は 4 月 1 日群になる:

# eval: 2025-01-01..2028-01-01
premise FY { calendar-system: Fiscal; tz: "Asia/Tokyo"; wkst: Mon }
@FY
everyDay |> within(year) |> first
#=> 2025-04-01 2026-04-01 2027-04-01

末日は 3 月 31 日群(4/1 の前日):

# eval: 2025-01-01..2028-01-01
premise FY { calendar-system: Fiscal; tz: "Asia/Tokyo"; wkst: Mon }
@FY
everyDay |> within(year) |> last
#=> 2025-03-31 2026-03-31 2027-03-31

fiscalMonthNo は「第 12 会計月」=翌暦年の 3 月を選び出せる(FY2026 の第 12 会計月の月初は 2027-03-01):

# eval: 2026-04-01..2027-04-01
premise FY { calendar-system: Fiscal; tz: "Asia/Tokyo"; wkst: Mon }
@FY
everyDay |> filter(d => fiscalMonthNo(d) == 12) |> within(month) |> first
#=> 2027-03-01

落とし穴(実装): ordinalIn(month, year, d) は点が枠窓(year)に属することを要求する。ここで言語意味論とリファレンス実装が食い違う。

3. なぜ一行で書けるか(機構 A と「閏は窓でなく値」)

派生の名前解決は機構 A(ADR-17・spec §3.7):

ピンが不要なのは、Gregorian が month を year に依存させない設計だからである。

quarter の自動追従を 2026 暦年で見る。ただし phase: 3 は 3 の倍数なので、切れ目の集合は Gregorian の 四半期と同一(1/1・4/1・7/1・10/1)——切れ目のレベルでは追従を観測できない。変わるのは所属で、 1/1 に始まる窓は暦の Q1 ではなく FY2025 の Q4(Jan–Mar)になる:

# eval: 2026-01-01..2027-01-01
premise FY { calendar-system: Fiscal; tz: "Asia/Tokyo"; wkst: Mon }
@FY
everyDay |> within(quarter) |> first
#=> 2026-01-01 2026-04-01 2026-07-01 2026-10-01

所属の変化は序数で観測できる——「第 4 会計四半期(1〜3 月)」に属する日々の四半期頭は 1/1 である:

# eval: 2026-01-01..2027-01-01
premise FY { calendar-system: Fiscal; tz: "Asia/Tokyo"; wkst: Mon }
@FY
everyDay |> filter(d => ordinalIn(quarter, year, d) == 4) |> within(quarter) |> first
#=> 2026-01-01

4. 日付は動かない(I1)

派生が動かすのは窓の切れ目だけで、暦日は不動(基底固定 I1・ADR-19)。2026-03-01 は会計暦でも「3 月 1 日」 のまま、所属する年窓だけが 2025 年度(Apr2025–Mar2026)に変わる。month に触れていないので、月末 (monthEnd)も Gregorian と完全に一致する——年度の切れ目(3/31→4/1)をまたいでも、2 月末(2026 年は非閏年 で 2/28)でも:

# eval: 2026-01-01..2026-07-01
premise FY { calendar-system: Fiscal; tz: "Asia/Tokyo"; wkst: Mon }
@FY
monthEnd
#=> 2026-01-31 2026-02-28 2026-03-31 2026-04-30 2026-05-31 2026-06-30

軸そのものを 3 か月平行移動する解釈(4 月が「1 月」に化ける類)は却下済みである(ADR-19 の解釈 Q。採用は 解釈 P=日付不動)—— 4 月は 4 月のまま、「第 1 会計月」という序数(fiscalMonthNo = 1)になるだけ。

5. 年度ラベル(開始年か終了年か)

年度の番号付けは、窓の切断とは独立の規約である(spec §3.7 の「直交する別ノブ」):

窓に名を付ける正式な担い手は、窓生成時の label: 付与式。束縛規則は ADR-34 で確定した——ラムダは 窓の先頭点を受け、意味論は定義的等式「名前(d) ≡ 付与式(d の属する窓の先頭点)」(評価は射影時・遅延):

# 開始暦年ラベル: 先頭点(4/1)の属する暦年を貼る。読み側は year(d) が年度番号を返す
year = month span (_ => 12) phase: 3 label: (p => yearNo(p))

読む側は今日でも値関数で書ける——Fiscal が同梱する fiscalYearNo がそれである。epochOrdinal(month, d) は点 d が属する暦月の通し序数(0 起点・ADR-31)。そこから位相ぶんの 3 を引いて「4 月始まりに位相をそろえた 月序数」にし、yearOf(= 1970 + m div 12。gregorian.md §1)で 12 か月ごとに区切れば開始暦年が出る。 FY2026 の初日:

# eval: 2025-01-01..2028-01-01
premise FY { calendar-system: Fiscal; tz: "Asia/Tokyo"; wkst: Mon }
@FY
everyDay |> filter(d => fiscalYearNo(d) == 2026) |> within(year) |> first
#=> 2026-04-01

末日は翌暦年の 3 月 31 日——2027-03-31 も fiscalYearNo = 2026 であり(1〜3 月は前年度に属する。 2026-01-15 なら 2025)、暦年を返す継承語 yearNo(= 2027)とここで食い違う:

# eval: 2025-01-01..2028-01-01
premise FY { calendar-system: Fiscal; tz: "Asia/Tokyo"; wkst: Mon }
@FY
everyDay |> filter(d => fiscalYearNo(d) == 2026) |> within(year) |> last
#=> 2027-03-31

窓インスタンス参照は premise 相対(ADR-42・落とし穴)——Fiscal の下の year(2026) は 2026 年度の日々(2026-04-01〜2027-03-31)であって暦年ではない。newYearHoliday \ year(2026) を 年度暦の下で書くと 2027 年 1 月の正月を消す(意図が 2026 年 1 月なら別の年度)。暦年が要るなら 修飾ピン Gregorian.year(2026)(機構 A——射影・インスタンス参照の両面に同一に効く):

# eval: 2026-03-30..2026-04-03
premise FY { calendar-system: Fiscal; tz: "Asia/Tokyo"; wkst: Mon }
@FY
year(2025) & Gregorian.year(2026)
#=> 2026-03-30 2026-03-31

(2025 年度∩暦年 2026=2026 年 1〜3 月。評価窓では年度末の 2 日だけが出る——年度と暦年の 食い違いがそのまま観測できる。)

6. 変種

US 連邦型(10 月始まり・終了年ラベル)は phase: 9 と補正 +3 の派生を自分で書く(31 U.S.C. §1102。 US FY2026 = 2025-10-01〜2026-09-30)。ラベルの補正は一般に、開始年規約が - phase・終了年規約が + ((12 - phase) mod 12)(日本型は - 3・US 型は + 3。phase: 0 では両規約が一致するので補正 0):

# eval: 2025-01-01..2028-01-01
premise USFiscal = Gregorian with {
  year = month span (_ => 12) phase: 9
  usFiscalYearNo = d => yearOf(epochOrdinal(month, d) + 3)
}
premise USFY { calendar-system: USFiscal; tz: "Asia/Tokyo"; wkst: Mon }
@USFY
everyDay |> within(year) |> first
#=> 2025-10-01 2026-10-01 2027-10-01

終了年ラベルの検証——US FY2026 の末日は 2026-09-30:

# eval: 2025-01-01..2028-01-01
premise USFiscal = Gregorian with {
  year = month span (_ => 12) phase: 9
  usFiscalYearNo = d => yearOf(epochOrdinal(month, d) + 3)
}
premise USFY { calendar-system: USFiscal; tz: "Asia/Tokyo"; wkst: Mon }
@USFY
everyDay |> filter(d => usFiscalYearNo(d) == 2026) |> within(year) |> last
#=> 2026-09-30

半期は Fiscal をさらに派生(派生の派生)して従属窓を一語足すだけ——上期 4〜9 月・下期 10〜3 月:

# eval: 2025-04-01..2026-04-01
premise FiscalHalf = Fiscal with { half = year split (_ => [6, 6]) by: month }
premise FYH { calendar-system: FiscalHalf; tz: "Asia/Tokyo"; wkst: Mon }
@FYH
everyDay |> within(half) |> first
#=> 2025-04-01 2025-10-01

射程外の「会計年度」もある。英国の個人課税年度(4 月 6 日開始)は日単位のずらしで、month ⊃ day の k(窓が含む単位の個数)が可変な組——rephase の射程(k 定数の組)の外であり、span の位相ずらし 一発では書けない(spec §3.7。必要になれば別演算子=宿題)。4-4-5 週会計(52/53 週制)も week 基準の別系統 で、Fiscal の変種ではなく別の premise として設計する問題である。

7. スコープ(Fiscal が負わないもの)