/**
* スケジュール関連の表示整形(`prismaSource.schedules()` 専用。DBに無い項目のサーバ生成)。
*
* ★曜日の起点は日曜★(`lib/fixtures/schedules.ts:6`「weekdays は『日月火水木金土』の7桁」)。
* この起点をフロントと2箇所に持たないこと(CLAUDE.md §9.6 / 指示書L 段階5-3)。
*/
const WEEKDAY_CHARS = ["日", "月", "火", "水", "木", "金", "土"] as const;
/**
* `weeks`(7桁。清掃する曜日が"1")から表示用ラベルを生成する。
*
* 「毎日」「平日のみ」「土日のみ」の3特例を先に判定し、それ以外は該当曜日を連結する。
* 該当曜日が1つも無ければ "なし" を返す(空文字を返すと画面が空欄になり、不具合と区別できない)。
* 桁が足りない文字列でも例外を投げない(存在しない桁は "1" と一致せず、単に選ばれないだけ)。
*/
export function weekdaysLabel(weeks: string): string {
switch (weeks) {
case "1111111":
return "毎日";
case "0111110":
return "平日のみ";
case "1000001":
return "土日のみ";
}
const days = WEEKDAY_CHARS.filter((_, i) => weeks[i] === "1");
return days.length > 0 ? days.join("") : "なし";
}
function pad2(n: number): string {
return String(n).padStart(2, "0");
}
/** `start_time`(HHMM。0000〜2359のみ。D-057 B-5)を "HH:MM" に整形する */
export function formatStartTime(hhmm: string): string {
const hour = Number.parseInt(hhmm.slice(0, 2), 10);
const minute = hhmm.slice(2, 4);
if (!(hour >= 0 && hour <= 23)) {
throw new RangeError(`formatStartTime: 想定外の時刻です(0〜23時のみ対応): ${hhmm}`);
}
return `${pad2(hour)}:${minute}`;
}
/**
* `end_time`(HHMM。時は24〜29を取りうる。D-057 B-5 / D-060)を整形する。
*
* 24〜29時は日跨ぎを表す。時から24を引いて「翌HH:MM」にする(例: "2830" → "翌04:30")。
* ★0〜29時の範囲外(例: "3000")は例外を投げる★ — DBの値域外なので、
* 静かに変な表示になるより止まるほうがよい。
*/
export function formatEndTime(hhmm: string): string {
const hour = Number.parseInt(hhmm.slice(0, 2), 10);
const minute = hhmm.slice(2, 4);
if (hour >= 24 && hour <= 29) {
return `翌${pad2(hour - 24)}:${minute}`;
}
if (hour >= 0 && hour <= 23) {
return `${pad2(hour)}:${minute}`;
}
throw new RangeError(`formatEndTime: 想定外の時刻です(0〜29時のみ対応): ${hhmm}`);
}