# 機能設計書 171-クロック時刻取得

## 概要

本ドキュメントは、libuv の `uv_clock_gettime()` 関数によるMONOTONIC/REALTIMEクロックの時刻取得機能について、その設計仕様を記載する。

### 本機能の処理概要

`uv_clock_gettime()` は、指定されたクロックID（MONOTONIC または REALTIME）に基づいて、ナノ秒精度の時刻を `uv_timespec64_t` 構造体に格納して返す関数である。

**業務上の目的・背景**：アプリケーションが正確な時刻情報を取得する必要がある場面は多い。経過時間の計測にはモノトニッククロック（巻き戻りのない単調増加時刻）が適しており、実世界の時刻取得にはリアルタイムクロックが適している。本機能はクロスプラットフォームで統一されたAPIを通じて、これらのクロック時刻をナノ秒精度で取得可能にする。`uv_hrtime()` が単なるナノ秒タイムスタンプ（uint64_t）を返すのに対し、本関数は秒+ナノ秒の構造化された時刻を返す点が異なる。

**機能の利用シーン**：タイムアウト計算、経過時間計測、ログへのタイムスタンプ付与、イベント間の時間差計測、外部システムとの時刻同期などに利用される。MONOTONIC クロックはシステム時刻の変更（NTPなど）に影響されないため、正確な経過時間の計測に最適である。

**主要な処理内容**：
1. 引数の NULL チェック（ts が NULL の場合 UV_EFAULT を返す）
2. clock_id に基づくクロック種別の判定
3. プラットフォーム固有のクロック取得APIの呼び出し
4. 結果を uv_timespec64_t 構造体に格納して返却

**関連システム・外部連携**：Unix 系では POSIX の `clock_gettime()` を使用し、Windows では `uv__hrtime()`（MONOTONIC）や `GetSystemTimePreciseAsFileTime()`（REALTIME）を使用する。

**権限による制御**：特別な権限は不要である。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | その他ユーティリティ | 主機能 | uv_clock_gettime()によるMONOTONIC/REALTIMEクロック取得のAPI定義 |

## 機能種別

データ取得処理（システム時刻の読み取り専用操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| clock_id | uv_clock_id | Yes | 取得するクロックの種類。UV_CLOCK_MONOTONIC または UV_CLOCK_REALTIME | UV_CLOCK_MONOTONIC, UV_CLOCK_REALTIME 以外の場合 UV_EINVAL |
| ts | uv_timespec64_t* | Yes | 時刻を格納する構造体へのポインタ | NULL の場合 UV_EFAULT |

### 入力データソース

OSカーネルが管理するシステムクロック（MONOTONIC: 起動からの経過時間、REALTIME: UTC基準の壁時計時刻）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ts->tv_sec | int64_t | 秒単位の時刻値 |
| ts->tv_nsec | int32_t | ナノ秒単位の端数（0-999999999） |
| 戻り値 | int | 成功時 0、失敗時は負のエラーコード |

### 出力先

呼び出し元に戻り値として返却。時刻データは引数として渡されたポインタ先の構造体に格納。

## 処理フロー

### 処理シーケンス

```
1. 引数チェック
   └─ ts が NULL なら UV_EFAULT を返す
2. クロック種別判定
   └─ clock_id が UV_CLOCK_MONOTONIC / UV_CLOCK_REALTIME 以外なら UV_EINVAL を返す
3. プラットフォーム固有のクロック取得
   └─ Unix: clock_gettime() を呼び出し
   └─ Windows: uv__hrtime()（MONOTONIC）/ GetSystemTimePreciseAsFileTime()（REALTIME）
4. 結果を構造体に格納
   └─ tv_sec と tv_nsec に値をセット
5. 成功時は 0 を返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{ts == NULL?}
    B -->|Yes| C[UV_EFAULT を返す]
    B -->|No| D{clock_id の判定}
    D -->|UV_CLOCK_MONOTONIC| E[MONOTONIC クロック取得]
    D -->|UV_CLOCK_REALTIME| F[REALTIME クロック取得]
    D -->|その他| G[UV_EINVAL を返す]
    E --> H{取得成功?}
    F --> H
    H -->|No| I[エラーコードを返す]
    H -->|Yes| J[ts に値を格納]
    J --> K[0 を返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-171-01 | クロックID検証 | UV_CLOCK_MONOTONIC と UV_CLOCK_REALTIME のみ有効 | 常時 |
| BR-171-02 | NULLポインタ検証 | ts が NULL の場合は UV_EFAULT を返す | 常時 |
| BR-171-03 | MONOTONIC の単調増加性 | MONOTONIC クロックはシステム時刻変更の影響を受けず単調増加する | UV_CLOCK_MONOTONIC 指定時 |

### 計算ロジック

Unix 系: POSIX `clock_gettime()` の結果をそのまま `uv_timespec64_t` にコピーする。
Windows MONOTONIC: `uv__hrtime(UV__NANOSEC)` で取得したナノ秒値を秒とナノ秒に分割（tv_sec = t / 1000000000, tv_nsec = t % 1000000000）。
Windows REALTIME: `GetSystemTimePreciseAsFileTime()` で取得した FILETIME（1601年1月1日からの100ナノ秒刻み）からエポック（1970年1月1日）を基準とした秒・ナノ秒に変換する。

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

### 操作別データベース影響一覧

該当なし（メモリ内操作のみ）。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EFAULT | パラメータエラー | ts が NULL | 有効なポインタを渡す |
| UV_EINVAL | パラメータエラー | clock_id が無効な値 | UV_CLOCK_MONOTONIC または UV_CLOCK_REALTIME を指定する |
| UV__ERR(errno) | システムエラー | Unix で clock_gettime() が失敗 | errno に応じた対処を行う |

### リトライ仕様

リトライは不要。即座に結果が返される同期関数である。

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

該当なし。

## パフォーマンス要件

同期的に完了する軽量な関数であり、通常ナノ秒からマイクロ秒オーダーで完了する。カーネルへのシステムコール1回で完了するため、パフォーマンス上の懸念は低い。

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

特別なセキュリティ要件はない。時刻情報の読み取りは一般的に権限不要である。

## 備考

- この関数は libuv issue #1674 を契機に追加された（src/unix/core.c L125 のコメントに記載）。
- `uv_hrtime()` がナノ秒精度のモノトニック時刻を `uint64_t` で返すのに対し、本関数は秒+ナノ秒で構造化された値を返し、REALTIME クロックにも対応している。
- uv_timespec64_t は 2038年問題への対応として int64_t を使用しているが、ソースコード中のコメント（include/uv.h L362）にて完全な2038年対応ではないことが注記されている。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | uv_clock_id 列挙体の定義（357-360行目）。UV_CLOCK_MONOTONIC=0, UV_CLOCK_REALTIME=1 の2値のみ |
| 1-2 | uv.h | `include/uv.h` | uv_timespec64_t 構造体の定義（368-371行目）。tv_sec(int64_t) + tv_nsec(int32_t) |

**読解のコツ**: `uv_clock_id` は POSIX の `CLOCK_MONOTONIC` / `CLOCK_REALTIME` に対応する libuv 独自の列挙型である。`uv_timespec64_t` は POSIX の `struct timespec` を64ビット対応にした構造体で、tv_sec が int64_t になっている点が異なる。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | API宣言（1836行目）: `int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts)` |

**主要処理フロー**:
1. **1836行目**: `uv_clock_gettime()` の関数シグネチャ。clock_id と ts ポインタを受け取り int を返す

#### Step 3: Unix実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | core.c | `src/unix/core.c` | Unix版の `uv_clock_gettime()` 実装（126-151行目） |

**主要処理フロー**:
- **130-131行目**: ts の NULL チェック。NULL なら UV_EFAULT を返す
- **133-142行目**: clock_id に基づく switch 文。CLOCK_MONOTONIC / CLOCK_REALTIME を判定し POSIX の `clock_gettime()` を呼び出す
- **134-135行目**: default ケースで UV_EINVAL を返す（無効な clock_id）
- **144-145行目**: clock_gettime() 失敗時、`UV__ERR(errno)` でerrno を UV エラーに変換して返す
- **147-148行目**: 成功時、`struct timespec` の値を `uv_timespec64_t` にコピー

#### Step 4: Windows実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | util.c | `src/win/util.c` | Windows版の `uv_clock_gettime()` 実装（428行目以降） |

**主要処理フロー**:
- **432-433行目**: ts の NULL チェック
- **436-441行目**: UV_CLOCK_MONOTONIC の場合、`uv__hrtime(UV__NANOSEC)` で取得したナノ秒値を秒とナノ秒に分割
- **442-443行目**: UV_CLOCK_REALTIME の場合、`GetSystemTimePreciseAsFileTime()` を使用

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

```
uv_clock_gettime(clock_id, ts)
    |
    +-- [Unix]
    |   +-- clock_gettime(CLOCK_MONOTONIC, &t)  [MONOTONIC]
    |   +-- clock_gettime(CLOCK_REALTIME, &t)   [REALTIME]
    |
    +-- [Windows]
        +-- uv__hrtime(UV__NANOSEC)             [MONOTONIC]
        +-- GetSystemTimePreciseAsFileTime(&ft)  [REALTIME]
```

### データフロー図

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

clock_id ──────────▶ uv_clock_gettime() ──────────▶ uv_timespec64_t* ts
(MONOTONIC/REALTIME)    |                               (tv_sec, tv_nsec)
                        |
                        +-- OS clock API呼び出し
                        +-- 結果を構造体に格納
                                                    ──▶ 戻り値 (int)
                                                        (0 / エラーコード)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | API宣言、uv_clock_id・uv_timespec64_t の型定義 |
| core.c | `src/unix/core.c` | ソース | Unix版の uv_clock_gettime() 実装 |
| util.c | `src/win/util.c` | ソース | Windows版の uv_clock_gettime() 実装 |
