# 機能設計書 79-カレンダー

## 概要

本ドキュメントは、Nushellのカレンダー機能の設計仕様を定義する。calコマンドは、カレンダーを表示する機能を提供する。

### 本機能の処理概要

カレンダー機能は、現在の月または指定された年のカレンダーを表示する機能である。テーブル形式で出力することも可能で、当日はハイライト表示される。週の開始曜日も変更可能。

**業務上の目的・背景**：カレンダーの表示は、日付の確認やスケジュール管理において基本的な機能である。本機能により、ターミナル上でカレンダーを確認でき、--as-tableオプションでデータとして処理することも可能。

**機能の利用シーン**：
- 今月のカレンダーを確認したい場合
- 特定の年の全カレンダーを表示したい場合
- 特定の曜日（例：金曜日の13日）を検索したい場合
- 週の開始曜日を月曜日に変更して表示したい場合

**主要な処理内容**：
1. 現在日付または指定年月の取得
2. 月の日数と開始曜日の計算
3. カレンダーテーブルの構築
4. 当日のハイライト処理
5. 文字列またはテーブルとして出力

**関連システム・外部連携**：
- chronoクレート：日付処理
- nu-color-config::StyleComputer：当日ハイライト

**権限による制御**：特になし。全ユーザーが使用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインREPL | 主画面 | calコマンドの実行と結果表示 |

## 機能種別

カレンダー表示機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --year (-y) | switch | No | 年カラムを表示 | - |
| --quarter (-q) | switch | No | 四半期カラムを表示 | - |
| --month (-m) | switch | No | 月カラムを表示 | - |
| --as-table (-t) | switch | No | テーブル形式で出力 | - |
| --full-year | Int | No | 指定年の全月カレンダーを表示 | - |
| --week-start | String | No | 週の開始曜日（su/mo/tu/we/th/fr/sa） | 有効な曜日 |
| --month-names | switch | No | 月名カラムを表示 | - |

### 入力データソース

コマンド引数のみ（パイプライン入力なし）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 通常出力 | String | 整形されたカレンダー文字列 |
| --as-table時 | Table | カレンダーテーブル |

### 出力先

標準出力（パイプライン出力）

## 処理フロー

### 処理シーケンス

```
1. cal コマンド
   └─ 現在日付を取得
   └─ --full-year指定時は月範囲を1-12に設定
   └─ 各月についてループ
       └─ MonthHelperで月情報を計算
       └─ --week-startで曜日オフセットを調整
       └─ 週ごとにレコードを生成
       └─ 当日をハイライト
   └─ --as-tableなら直接出力、そうでなければtableコマンドで整形
```

### フローチャート

```mermaid
flowchart TD
    A[cal コマンド] --> B[現在日付取得]
    B --> C{--full-year?}
    C -->|Yes| D[月範囲: 1-12]
    C -->|No| E[月範囲: 現在月のみ]
    D --> F[月ループ開始]
    E --> F
    F --> G[MonthHelper作成]
    G --> H{--week-start?}
    H -->|Yes| I[曜日配列をローテート]
    H -->|No| J[デフォルト: 日曜開始]
    I --> K[週ループ]
    J --> K
    K --> L[レコード構築]
    L --> M{当日?}
    M -->|Yes| N[スタイル適用してハイライト]
    M -->|No| O[通常の数値]
    N --> P[次の週へ]
    O --> P
    P --> Q{月ループ終了?}
    Q -->|No| F
    Q -->|Yes| R{--as-table?}
    R -->|Yes| S[テーブルとして出力]
    R -->|No| T[tableコマンドで整形]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-79-1 | 週の開始 | デフォルトは日曜日（su）開始 | --week-start未指定時 |
| BR-79-2 | 当日ハイライト | 現在月の当日はヘッダースタイルでハイライト | 当日を含む月の表示時 |
| BR-79-3 | 曜日カラム | su/mo/tu/we/th/fr/saの7カラム | 常時 |
| BR-79-4 | 空セル | 月の開始前・終了後はnothing | 常時 |
| BR-79-5 | 四半期計算 | (month - 1) / 3 + 1 | --quarter指定時 |

### 計算ロジック

#### 月の日数計算

```
翌月1日の前日 = 当月の最終日
days_in_month = (next_month_1st - 1day).day()
```

#### 開始曜日オフセット

```
base_offset = 月1日の曜日（日曜=0）
--week-start指定時:
  position = week_startの位置
  total_offset = (base_offset + (7 - position)) % 7
```

## データベース操作仕様

該当なし（本機能はデータベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | TypeMismatch | 無効な年が指定された | 有効な年を指定 |
| - | TypeMismatch | 無効な--week-startが指定された | su/mo/tu/we/th/fr/saを指定 |
| - | UnknownOperator | 内部パースエラー | - |

### リトライ仕様

リトライは行わない。

## トランザクション仕様

該当なし

## パフォーマンス要件

特になし

## セキュリティ考慮事項

特になし

## 備考

- 曜日カラムは2文字の略称（su, mo, tu, we, th, fr, sa）
- --full-yearで年間カレンダーを表示すると、52-53週分のテーブルが生成される
- StyleComputerでヘッダースタイルを取得して当日をハイライト

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

MonthHelper構造体を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cal.rs | `crates/nu-command/src/generators/cal.rs` | MonthHelper構造体（185-229行目） |

**読解のコツ**: MonthHelperは月の開始曜日、日数、四半期、月名を計算するヘルパー構造体。

#### Step 2: メイン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cal.rs | `crates/nu-command/src/generators/cal.rs` | cal関数（101-176行目） |
| 2-2 | cal.rs | `crates/nu-command/src/generators/cal.rs` | add_month_to_table関数（277-399行目） |

**主要処理フロー** (cal.rs):
- **8行目**: DAYS_OF_THE_WEEK定数
- **101-176行目**: cal関数 - メインロジック
- **110行目**: get_current_date()で現在日付取得
- **128-137行目**: --full-year時の月範囲設定
- **139-148行目**: add_months_of_year_to_tableで月を追加
- **166-175行目**: --as-tableの分岐（tableコマンド呼び出しまたは直接出力）

**月追加処理** (cal.rs):
- **277-301行目**: MonthHelper作成と検証
- **303-322行目**: --week-startの処理（曜日ローテーション）
- **332-396行目**: 週ごとのレコード構築
- **374-387行目**: 当日のハイライト処理

### プログラム呼び出し階層図

```
Cal::run (cal.rs)
    └─ cal()
           ├─ get_current_date()
           ├─ Arguments構造体作成
           ├─ StyleComputer::from_config()
           │
           ├─ add_months_of_year_to_table()
           │      └─ add_month_to_table() [各月]
           │             ├─ MonthHelper::new()
           │             ├─ 曜日ローテーション（--week-start時）
           │             ├─ 週レコード構築
           │             └─ 当日ハイライト
           │
           └─ 出力
                  ├─ --as-table: PipelineData
                  └─ 通常: Table.run()
```

### データフロー図

```
[cal]
引数/フラグ ───▶ Arguments ───▶ 月範囲計算 ───▶ 月ループ
                                                    │
                                                    ▼
                                            MonthHelper
                                                    │
                                                    ▼
                                            週レコード生成
                                                    │
                ┌───────────────────────────────────┘
                │
                ▼
        VecDeque<Value> ───▶ 出力
                                │
                ┌───────────────┼───────────────┐
                │               │               │
                ▼               ▼               ▼
            --as-table      tableコマンド   当日ハイライト
            (テーブル)       (文字列)       (StyleComputer)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cal.rs | `crates/nu-command/src/generators/cal.rs` | ソース | calコマンド |
| mod.rs | `crates/nu-command/src/generators/mod.rs` | ソース | generatorsモジュール定義 |
