# 機能設計書: times - 日時操作

## 1. 機能概要

### 1.1 目的
timesモジュールは、Nimプログラミング言語における包括的な日時操作機能を提供する。日付・時刻の表現、タイムゾーン処理、時間計算、フォーマット・パース機能を備え、クロスプラットフォームで動作する。

### 1.2 機能範囲
- 日時の表現（DateTime, Time, Duration）
- タイムゾーン処理（Timezone, UTC, ローカル）
- 日時の算術演算（加算、減算、比較）
- 日時のフォーマットとパース
- ISO 8601週番号の計算
- うるう年、曜日、年間通算日の計算

### 1.3 関連コンポーネント
- `monotimes` モジュール: モノトニック時間
- `strutils` モジュール: 文字列操作
- プラットフォーム固有のCライブラリ（POSIX/Windows）

## 2. データ構造

### 2.1 主要な型定義

```nim
type
  Month* = enum  ## 月の列挙型
    mJan = 1, mFeb, mMar, mApr, mMay, mJun,
    mJul, mAug, mSep, mOct, mNov, mDec

  WeekDay* = enum  ## 曜日の列挙型
    dMon, dTue, dWed, dThu, dFri, dSat, dSun

  Time* = object  ## Unixエポックからの時間
    seconds: int64           ## 秒数
    nanosecond: NanosecondRange  ## ナノ秒（0-999999999）

  DateTime* = object  ## 人間可読な日時表現
    nanosecond*: NanosecondRange
    second*: SecondRange     ## 0-59
    minute*: MinuteRange     ## 0-59
    hour*: HourRange         ## 0-23
    monthday*: MonthdayRange ## 1-31
    month*: Month
    year*: int
    weekday*: WeekDay
    yearday*: YeardayRange   ## 0-365
    isDst*: bool             ## 夏時間フラグ
    timezone*: Timezone      ## タイムゾーン
    utcOffset*: int          ## UTCオフセット（秒）

  Duration* = object  ## 時間間隔
    seconds: int64
    nanosecond: int  ## -999999999〜999999999

  Timezone* = ref object  ## タイムゾーン
    name: string
    zonedTimeFromTimeImpl: proc (...)
    zonedTimeFromAdjTimeImpl: proc (...)
```

### 2.2 範囲型

| 型名 | 範囲 | 説明 |
|------|------|------|
| `NanosecondRange` | 0..999999999 | ナノ秒 |
| `SecondRange` | 0..59 | 秒 |
| `MinuteRange` | 0..59 | 分 |
| `HourRange` | 0..23 | 時 |
| `MonthdayRange` | 1..31 | 日 |
| `YeardayRange` | 0..365 | 年間通算日 |
| `IsoWeekRange` | 1..53 | ISO週番号 |

### 2.3 時間単位

```nim
type
  TimeUnit* = enum
    Nanoseconds, Microseconds, Milliseconds,
    Seconds, Minutes, Hours, Days, Weeks,
    Months, Years

  FixedTimeUnit* = range[Nanoseconds..Weeks]  ## 固定長単位
```

## 3. 主要機能

### 3.1 現在時刻の取得

#### getTime
```nim
proc getTime*(): Time
```
- **目的**: 現在時刻をTime型で取得
- **精度**: ナノ秒まで（プラットフォーム依存）
- **ソース位置**: `lib/pure/times.nim:978-1000`

#### now
```nim
proc now*(): DateTime
```
- **目的**: 現在のローカル日時を取得
- **ソース位置**: `lib/pure/times.nim`（getTime().local()を使用）

### 3.2 DateTime作成

#### initDateTime
```nim
proc initDateTime*(monthday: MonthdayRange, month: Month, year: int,
                   hour: HourRange, minute: MinuteRange, second: SecondRange,
                   nanosecond: NanosecondRange, zone: Timezone = local()): DateTime
```
- **目的**: 日時コンポーネントからDateTimeを作成
- **バリデーション**: 日付の妥当性を検証
- **ソース位置**: `lib/pure/times.nim`

### 3.3 Duration操作

#### initDuration
```nim
proc initDuration*(nanoseconds, microseconds, milliseconds,
                   seconds, minutes, hours, days, weeks: int64 = 0): Duration
```
- **目的**: 時間間隔を作成
- **特徴**: 正規化して保存（秒とナノ秒に分割）
- **ソース位置**: `lib/pure/times.nim:665-685`

#### Duration変換プロシージャ

| プロシージャ | 説明 | ソース位置 |
|-------------|------|-----------|
| `inWeeks` | 週数に変換 | 706-711 |
| `inDays` | 日数に変換 | 713-718 |
| `inHours` | 時間数に変換 | 720-725 |
| `inMinutes` | 分数に変換 | 727-732 |
| `inSeconds` | 秒数に変換 | 734-739 |
| `inMilliseconds` | ミリ秒数に変換 | 741-746 |
| `inMicroseconds` | マイクロ秒数に変換 | 748-753 |
| `inNanoseconds` | ナノ秒数に変換 | 755-760 |

### 3.4 Time変換

#### Unix時間変換

```nim
proc fromUnix*(unix: int64): Time      ## Unixタイムスタンプから変換
proc toUnix*(t: Time): int64           ## Unixタイムスタンプに変換
proc fromUnixFloat(seconds: float): Time  ## サブ秒精度で変換
proc toUnixFloat(t: Time): float       ## サブ秒精度で変換
```
- **ソース位置**: `lib/pure/times.nim:924-959`

#### Windows時間変換

```nim
proc fromWinTime*(win: int64): Time    ## Windowsファイル時刻から変換
proc toWinTime*(t: Time): int64        ## Windowsファイル時刻に変換
```
- **ソース位置**: `lib/pure/times.nim:962-973`

### 3.5 日付計算

#### 曜日・年間通算日

```nim
proc getDayOfWeek*(monthday: MonthdayRange, month: Month, year: int): WeekDay
proc getDayOfYear*(monthday: MonthdayRange, month: Month, year: int): YeardayRange
proc getDaysInYear*(year: int): int
proc getDaysInMonth*(month: Month, year: int): int
proc isLeapYear*(year: int): bool
```
- **ソース位置**: `lib/pure/times.nim:520-562`

#### ISO週番号

```nim
proc getIsoWeekAndYear*(dt: DateTime): tuple[isoweek: IsoWeekRange, isoyear: IsoYear]
proc getWeeksInIsoYear*(y: IsoYear): IsoWeekRange
```
- **ソース位置**: `lib/pure/times.nim:567-610`

### 3.6 算術演算

#### Duration演算

```nim
proc `+`*(a, b: Duration): Duration    ## 加算
proc `-`*(a, b: Duration): Duration    ## 減算
proc `-`*(a: Duration): Duration       ## 符号反転
proc `*`*(a: int64, b: Duration): Duration  ## スカラー乗算
proc `div`*(a: Duration, b: int64): Duration  ## 整数除算
```
- **ソース位置**: `lib/pure/times.nim:816-895`

#### Time演算

```nim
proc `+`*(t: Time, d: Duration): Time
proc `-`*(t: Time, d: Duration): Time
proc `-`*(a, b: Time): Duration
```

## 4. タイムゾーン処理

### 4.1 タイムゾーン取得

```nim
proc utc*(): Timezone    ## UTCタイムゾーン
proc local*(): Timezone  ## ローカルタイムゾーン
```

### 4.2 タイムゾーン変換

```nim
proc utc*(t: Time): DateTime     ## TimeをUTCのDateTimeに変換
proc local*(t: Time): DateTime   ## TimeをローカルのDateTimeに変換
proc inZone*(dt: DateTime, zone: Timezone): DateTime  ## タイムゾーン変換
proc toTime*(dt: DateTime): Time ## DateTimeをTimeに変換
```

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

### 5.1 推奨読解順序

1. **型定義** (最初の200行程度)
   - `Time`, `DateTime`, `Duration`の構造を理解

2. **ユーティリティ関数** (400-560行目)
   - `isLeapYear`, `getDayOfWeek`, `getDayOfYear`など

3. **Duration操作** (655-910行目)
   - `initDuration`, 変換プロシージャ, 演算子

4. **Time操作** (915-1000行目)
   - `initTime`, `fromUnix`, `toUnix`, `getTime`

5. **DateTime操作** (initDateTimeなど)
   - 日時の作成とタイムゾーン処理

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

```
getTime() [978行目]
├── [JS] newDate().getTime()
├── [macOS] gettimeofday()
├── [POSIX] clock_gettime(CLOCK_REALTIME)
└── [Windows] GetSystemTimeAsFileTime()
    └── initTime(seconds, nanosecond)

initDuration() [665行目]
├── convert(Weeks/Days/Hours/..., Seconds)
├── 秒とナノ秒に正規化
└── normalize[Duration]()

DateTime演算
├── dt + Duration
│   └── toTime(dt) + duration -> inZone(result, dt.timezone)
└── dt - Duration
    └── toTime(dt) - duration -> inZone(result, dt.timezone)
```

### 5.3 データフロー図

```
[現在時刻取得]
      │
      ▼
   getTime() ──────────────────┐
      │                        │
      ▼                        ▼
   Time型                   Duration型
   (秒 + ナノ秒)            (秒 + ナノ秒)
      │                        │
      ├── .utc() ──────┐       ├── inSeconds()
      └── .local() ────┤       ├── inDays()
                       ▼       └── toParts()
                  DateTime型
                  (年月日時分秒+タイムゾーン)
                       │
                       ├── format()
                       ├── + Duration
                       └── toTime()
```

### 5.4 読解のコツ

- **正規化**: `normalize`テンプレートは秒とナノ秒を正規化（ナノ秒は0〜999999999の範囲に）
- **エポック計算**: `toEpochDay`/`fromEpochDay`は1970-01-01からの日数を計算（Howard Hinnantのアルゴリズム）
- **タイムゾーン**: `Timezone`はプロシージャを保持し、動的に変換を行う
- **プラットフォーム分岐**: `when defined(js/macosx/posix/windows)`で分岐

## 6. 関連ファイル一覧

| ファイルパス | 種別 | 役割 |
|-------------|------|------|
| `lib/pure/times.nim` | ソース | メイン実装 |
| `lib/std/monotimes.nim` | ソース | モノトニック時間 |
| `lib/posix/posix.nim` | ソース | POSIX時間関数 |
| `lib/windows/winlean.nim` | ソース | Windows API |

## 7. 設計上の考慮事項

### 7.1 精度
- Time型はナノ秒精度だが、実際の精度はプラットフォーム依存
- JavaScript: ミリ秒精度
- POSIX/Windows: ナノ秒まで取得可能（ただし実際の精度はシステム依存）

### 7.2 タイムゾーン
- UTCとローカルタイムゾーンを標準サポート
- カスタムタイムゾーンは`Timezone`型を直接作成して対応

### 7.3 ISO 8601準拠
- ISO週番号の正確な計算をサポート
- 年またぎの週（第1週が前年、第52/53週が翌年）に対応

### 7.4 パフォーマンス
- Duration演算は整数演算のみで高速
- タイムゾーン変換はプロシージャ呼び出しを伴う
