締め切りまで、あと何営業日・何時間——「残り」は点を数える

Kairos

1. 「あと何日」の答えは 3 つある

月曜の午後 2 時。締め切りは来週水曜(11 月 4 日)の 17 時。「あと何日使えるか」と聞かれて、暦を数えれば 9 日、営業日を数えれば 6 日——間に 11 月 3 日(文化の日)が挟まる——、「使える時間」なら今日の残りと当日の 17 時までを足して 51 時間、と答えが 3 つある。

Excel なら NETWORKDAYS に祝日表を渡せば営業日は数えられる。Kairos には「残り日数を返す」語は無い。代わりに、「いつ」の列を聞く範囲で切り、出てきた点を数える。定義は「いつでも成り立つ規則」、範囲は「いつからいつまで聞くか」——前回の §5 で書いた分け方が、ここでは数える道具になる。

2. 営業日を数える——列を [今日, 締め切り日) で聞く

祝日表と営業日の列を前文に置く(「月 2 回」の回の §3 と同じ)。本体は bizDay だけ:

premise JP {
  calendar-system: Gregorian; tz: "Asia/Tokyo"; wkst: Mon
  national = [2026-01-01, 2026-01-12, 2026-02-11, 2026-02-23, 2026-03-20, 2026-04-29, 2026-05-03..2026-05-06,
              2026-07-20, 2026-08-11, 2026-09-21..2026-09-23, 2026-10-12, 2026-11-03, 2026-11-23] covering: 2026..2026
  satSun = everyDay |> filter(d => weekday(d) == Sat or weekday(d) == Sun)
  bizDay = everyDay \ (satSun | national)
}

@JP
bizDay

今日から締め切り日の手前まで:

$ kairos list --from 2026-10-26 --to 2026-11-04 days.kairos
2026-10-26
2026-10-27
2026-10-28
2026-10-29
2026-10-30
2026-11-02
# 被覆サマリ
#   JP.national covering 2026-01-01..2026-12-31 残走路 58 日

6 行。10 月 31 日・11 月 1 日の土日と、11 月 3 日の文化の日が落ちている。締め切り当日も数えるなら --to 2026-11-05 で 7 行。from, to) は右端を含まない([半開区間の回)ので、「当日を含めるか」は --to を 1 日ずらすだけで決まる。

図 1: 10 月 26 日から 11 月 4 日までの 10 日の帯。営業日 6 日に点、土日は灰、11 月 3 日は赤。下段は営業日ごとの 9〜16 時の 8 コマで、初日は 14 時から、締め切り当日は 16 時まで。塗られたコマは 51。
図 1: 10 月 26 日から 11 月 4 日までの 10 日の帯。営業日 6 日に点、土日は灰、11 月 3 日は赤。下段は営業日ごとの 9〜16 時の 8 コマで、初日は 14 時から、締め切り当日は 16 時まで。塗られたコマは 51。

数えるのは呼ぶ側の仕事で、--json で受ければ行数を数えるだけになる:

$ kairos list --from 2026-10-26 --to 2026-11-04 --json days.kairos | jq '.results[0].dates | length'
6

PowerShell なら (kairos list … --json days.kairos | ConvertFrom-Json).results[0].dates.Count。

3. 営業時間を数える——正時の点を isOpen で絞る

「あと何時間」は、営業時間内の毎正時を点にして数える。会社の営業時間を 9 時から 17 時として、営業時間の定義はisOpen の回の器をそのまま使う:

premise Office {
  calendar-system: Gregorian
  tz: "Asia/Tokyo"
  source: "example"
  satSunC = everyDay |> filter(d => weekday(d) == Sat or weekday(d) == Sun)
  holidays = [2026-10-12, 2026-11-03, 2026-11-23] covering: 2026-10-01..2026-12-31
  nonWorking = satSunC | holidays
  nine = chronos grid 1d anchor: 2026-01-01T09:00
  five = chronos grid 1d anchor: 2026-01-01T17:00
  sessionOpens  = nine |> first
  sessionCloses = five |> first
}
premise JP {
  calendar-system: Gregorian
  calendar: Office
  tz: "Asia/Tokyo"
  wkst: Mon
  hourly = everyInstant |> strideBy(1h, from: 2026-01-01)
}

@JP
hourly |> filter(t => isOpen(t))

hourly は毎正時の列、isOpen(t) は「その瞬間に開いているか」。9 時から 17 時の手前までで、1 日 8 点。[2026-10-26, 2026-11-04) で聞くと営業日 6 日 × 8 点 = 48 点が出る。

ただし、これでは「今日の 14 時まで」の分と「締め切り当日の 17 時まで」の分が合わない。--from・--to は日付で指定するので、時刻の切り出しは式の中で書く。「時」の通し番号(epochOrdinal(hour, t))を比べる:

hourly |> filter(t => isOpen(t)
  and epochOrdinal(hour, t) >= epochOrdinal(hour, 2026-10-26T14:00)
  and epochOrdinal(hour, t) <  epochOrdinal(hour, 2026-11-04T17:00))
$ kairos list --from 2026-10-26 --to 2026-11-05 hours.kairos
2026-10-26T14:00
2026-10-26T15:00
2026-10-26T16:00
2026-10-27T09:00
(略)
2026-11-04T15:00
2026-11-04T16:00
# 被覆サマリ
#   Office.holidays covering 2026-10-01..2026-12-31 残走路 57 日

51 行。今日の残り 3 点(14・15・16 時)、間の 5 営業日で 40 点、締め切り当日の 8 点(9 時から 16 時)。「14 時から」と「17 時の手前まで」が、それぞれ >= と < に写っている。

4. 落とし穴

  • 「51 時間」は正時の点の数。14 時 30 分に聞いても、14 時台のコマは 1 つと数える。分単位の端数が要るなら、 「数えるコマの幅」を先に決める(strideBy(30m, …) にすれば 30 分刻みで 102 点)。
  • 祝日表の期限。被覆サマリの「残走路 57 日」は、祝日表が 12 月末で切れていることを言っている。年を跨ぐ締め切りを 数える前に表を延ばす(祝日表は黙って腐る)。
  • 会議や移動を引くなら、前回の \ の型。会議の列を正時の点で作って hourly \ meetings と引けば、「使える時間」に近づく。ただし 30 分の会議を 1 時間のコマから引くかどうかは、書き手が決める。
  • 「今」は式に埋めない。2026-10-26T14:00 は例のために直書きしたが、毎朝聞くなら呼ぶ側が今日の日付を --from に 入れ、時刻の切り出しは定義に書かずに --json で受けた点を手元で切る方が素直である。

5. 動かす

毎朝 9 時に「残り営業日」を数えて知らせるなら、月末最終営業日の自動実行まで通すの型 1 で--from を今日、--to を締め切り日にする。Windows ならWindows Update の回の §6 のガイドのPowerShell が、--json を ConvertFrom-Json で受けて .Count を取るところまで同じ型で書ける。

まとめ

  • 「あと何日」には暦の日数・営業日・使える時間の 3 つの答えがある。Kairos に「残りを返す」語は無く、列を範囲で切って点を数える
  • 営業日: bizDay を [今日, 締め切り日) で聞く。当日を含めるかは --to を 1 日ずらす
  • 営業時間: hourly |> filter(t => isOpen(t)) で 1 日 8 点。時刻の切り出しは epochOrdinal(hour, …) の比較で式に書く
  • 「51 時間」は正時のコマの数。端数の扱いと会議の除外は書き手が決める
  • 数えるのは呼ぶ側。--json で受けて行数を数える

▶ Playground で定義を実行する——10 月 26 日 14 時から 11 月 4 日 17 時までの営業時間 51 点が出る。コメントにある bizDay の行と入れ替えると営業日 7 点(締め切り当日を含む)になる。ブラウザ内で完結し、何も送信しない。


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

コメント

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