# 機能設計書 54-Timeクラス

## 概要

本ドキュメントは、mrubyにおけるTimeクラスの設計を記述する。Timeクラスは日時の取得・操作・フォーマット等の時刻処理機能を提供し、POSIX time_tに基づくマイクロ秒精度の時刻管理を行う。

### 本機能の処理概要

Timeクラスは、現在時刻の取得、日時コンポーネント（年月日時分秒）へのアクセス、UTC/ローカル時間の変換、時刻の加減算、文字列表現への変換など、包括的な時刻操作を提供する。

**業務上の目的・背景**：タイムスタンプの生成、ログの時刻記録、タイムアウト制御、スケジュール管理など、組み込みシステムにおいても時刻管理は基本的な要件である。mrubyのTimeクラスはCRuntime関数（gettimeofday, mktime, gmtime_r等）をラップして、Ruby互換のAPIを提供する。

**機能の利用シーン**：現在時刻の取得（Time.now）、特定日時の生成（Time.new/Time.mktime）、日時文字列の出力（to_s）、経過時間の計算（時刻の差分）、UTC/ローカル変換など。

**主要な処理内容**：
1. 現在時刻の取得（gettimeofday/clock_gettime利用）
2. 年月日時分秒からの時刻生成（mktime/timegm利用）
3. 日時コンポーネントのアクセサ（year, month, day, hour, min, sec, usec等）
4. UTC/ローカルタイムゾーン変換（gmtime_r/localtime_r利用）
5. 時刻の加減算（秒数の加減）
6. 文字列フォーマット出力

**関連システム・外部連携**：POSIX時刻関数（gettimeofday, mktime, gmtime_r, localtime_r）に依存。Windowsプラットフォームではポリフィルを提供。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | ライブラリ機能であり、画面との直接的関連なし |

## 機能種別

日時処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| year | Integer | No（Time.new時） | 年 | 整数値 |
| month | Integer | No | 月（1-12） | 1-12の範囲 |
| day | Integer | No | 日（1-31） | 1-31の範囲 |
| hour | Integer | No | 時（0-23） | 0-23の範囲 |
| min | Integer | No | 分（0-59） | 0-59の範囲 |
| sec | Integer/Float | No | 秒（0-60） | 0-60の範囲 |
| usec | Integer | No（at時） | マイクロ秒 | 0-999999の範囲 |
| timezone | Symbol | No | タイムゾーン（:utc, :local） | :utc または :local |

### 入力データソース

Rubyプログラムからの直接呼び出し、およびシステムクロック。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Timeオブジェクト | Time | 時刻を表すオブジェクト |
| 日時コンポーネント | Integer | year/month/day/hour/min/sec/usec等 |
| to_s結果 | String | "YYYY-MM-DD HH:MM:SS +HHMM"形式 |
| to_f結果 | Float | Unix epochからの秒数（浮動小数点） |
| to_i結果 | Integer | Unix epochからの秒数（整数） |

### 出力先

呼び出し元のRubyプログラムへの戻り値。

## 処理フロー

### 処理シーケンス

```
1. Time.now / Time.new の呼び出し
   └─ gettimeofday() または clock_gettime() でシステム時刻取得
2. 内部struct mrb_timeに時刻データを格納
   └─ time_t sec（秒）、time_t usec（マイクロ秒）、timezone情報
3. 必要に応じてstruct tmへの変換
   └─ gmtime_r()（UTC）または localtime_r()（ローカル）
4. 日時コンポーネントへのアクセス
   └─ struct tmの各フィールドからの取得
```

### フローチャート

```mermaid
flowchart TD
    A[Time.now/Time.new] --> B{引数あり?}
    B -->|No| C[gettimeofday で現在時刻取得]
    B -->|Yes| D[年月日時分秒から mktime/timegm で変換]
    C --> E[struct mrb_time に格納]
    D --> E
    E --> F{メソッド呼び出し}
    F -->|year/month等| G[gmtime_r/localtime_r でstruct tm変換]
    F -->|to_s| H[strftime相当の文字列生成]
    F -->|to_f/to_i| I[sec + usec/1000000を返却]
    F -->|utc/localtime| J[タイムゾーン変換]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-54-01 | タイムゾーン | MRB_TIMEZONE_UTC(1), MRB_TIMEZONE_LOCAL(2)の2種をサポート | 常時 |
| BR-54-02 | マイクロ秒精度 | 時刻はマイクロ秒精度（USECS_PER_SEC = 1000000）で管理 | 常時 |
| BR-54-03 | 閏年判定 | 4で割り切れ、かつ100で割り切れないか400で割り切れる年が閏年 | timegm計算時 |
| BR-54-04 | TO_S形式 | "%Y-%m-%d %H:%M:%S "形式で出力 | to_s呼び出し時 |

### 計算ロジック

- timegm（独自実装）: 年月日時分秒からUnix epoch秒を算出
- 閏年判定: (y % 4 == 0) && ((y % 100 != 0) || (y % 400 == 0))
- Windows gettimeofday: FILETIME → Unix epoch変換（WINDOWS_EPOCH_BIAS_USEC差分）

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentError | 不正な日時パラメータ | 有効な日時値を指定 |
| - | RuntimeError | gmtime_r/localtime_rの失敗 | システム時刻の正常性確認 |

### リトライ仕様

リトライ不要。

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

該当なし。

## パフォーマンス要件

- gettimeofday()はシステムコールであり、呼び出し頻度に注意
- struct tmへの変換はアクセス時に遅延評価

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

- 時刻データはシステムクロックに依存するため、時刻改ざんの影響を受ける

## 備考

- USE_CLOCK_GETTIMEマクロによりclock_gettime利用が可能
- NO_GETTIMEOFDAY/NO_GMTIME_R等のマクロでプラットフォーム互換性を管理
- Windows環境ではgettimeofdayのポリフィルが提供される
- mrb_time_at() C APIでC言語からTimeオブジェクトを生成可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | time.h | `mrbgems/mruby-time/include/mruby/time.h` | mrb_timezone列挙型（NONE/UTC/LOCAL）の定義（15-20行目） |
| 1-2 | time.h | `mrbgems/mruby-time/include/mruby/time.h` | mrb_time_at/mrb_time_get_tm C API宣言（22-23行目） |
| 1-3 | time.c | `mrbgems/mruby-time/src/time.c` | 時間単位定数の定義（30-38行目） |
| 1-4 | time.c | `mrbgems/mruby-time/src/time.c` | カレンダー計算定数の定義（41-45行目） |

**読解のコツ**: time.cの冒頭にはプラットフォーム判定マクロ（MRB_TIME_WINDOWS_NO_STRFTIME_Z, NO_GETTIMEOFDAY, NO_GMTIME_R等）が多数定義されている。これらは対象プラットフォームに応じた条件コンパイルを制御する。

#### Step 2: プラットフォーム互換層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | time.c | `mrbgems/mruby-time/src/time.c` | Windows gettimeofday ポリフィル（145-163行目） |
| 2-2 | time.c | `mrbgems/mruby-time/src/time.c` | gmtime_r/localtime_rのWindows互換マクロ（88-93行目） |
| 2-3 | time.c | `mrbgems/mruby-time/src/time.c` | 独自timegm実装（is_leapyear + timegm）（184-200行目） |

#### Step 3: 独自timegm実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | time.c | `mrbgems/mruby-time/src/time.c` | is_leapyear()関数（184-188行目） |
| 3-2 | time.c | `mrbgems/mruby-time/src/time.c` | timegm()関数 - struct tmからtime_tへの変換（190-200行目） |

**主要処理フロー**:
- **193-196行目**: ndaysテーブル（通常年・閏年それぞれの月別日数）
- **200行目**: 年/月のループで累積秒数を計算

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

```
Time.now / Time.new
    |
    +-- gettimeofday() / clock_gettime()  [現在時刻取得]
    |
    +-- mktime() / timegm()  [日時パラメータから変換]
    |    +-- is_leapyear()
    |
    +-- gmtime_r() / localtime_r()  [struct tmへの変換]

Time#year / #month / #day 等
    |
    +-- struct tmからの値取得

Time#to_s
    |
    +-- strftime相当処理
```

### データフロー図

```
[入力]                      [処理]                       [出力]

システムクロック  ──────> gettimeofday()  ──────────> Time オブジェクト
                                                     (sec, usec, timezone)
年月日時分秒     ──────> mktime()/timegm() ──────>
                                                     |
                                                     v
                         gmtime_r()/localtime_r() -> struct tm
                                                     |
                                                     v
                                                   year/month/day/...
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| time.c | `mrbgems/mruby-time/src/time.c` | ソース | Timeクラスの主要C実装 |
| time.h | `mrbgems/mruby-time/include/mruby/time.h` | ヘッダ | C API宣言、mrb_timezone定義 |
| time.rb | `mrbgems/mruby-time/test/time.rb` | テスト | Timeクラスの動作テスト |
| mrbgem.rake | `mrbgems/mruby-time/mrbgem.rake` | 設定 | gemメタデータ定義 |
