# 機能設計書 98-Dates

## 概要

本ドキュメントは、Julia標準ライブラリのDatesモジュールの設計を記述する。日付（Date）、日時（DateTime）、時刻（Time）の各型と、期間（Period）型、およびそれらに対する算術演算、クエリ、フォーマット、パースなどの操作を提供する機能である。

### 本機能の処理概要

**業務上の目的・背景**：時間データの操作はほぼ全てのアプリケーションで必要とされる基本機能である。Datesモジュールは、ISO 8601準拠の先発グレゴリオ暦に基づく日付・時刻型と、それらの演算・変換・フォーマット機能を提供する。タイムゾーンは含まず、UTベースの86400秒/日を基本とする。

**機能の利用シーン**：日付の生成・比較・算術演算、期間の計算（年/月/日/時/分/秒）、日付文字列のパース・フォーマット、曜日・月名のクエリ、Unix時刻との変換、日付範囲の生成。

**主要な処理内容**：
1. 型システム：AbstractTime → Period/Instant/TimeType の型階層
2. 期間型（Period）：Year, Quarter, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond
3. 日付・時刻型：Date（日精度）、DateTime（ミリ秒精度）、Time（ナノ秒精度）
4. アクセサ：year(), month(), day(), hour(), minute(), second()等
5. クエリ：dayofweek(), isleapyear(), daysinmonth(), dayname(), monthname()等
6. 算術演算：日付+期間、日付-日付
7. 変換：unix2datetime(), now(), today(), rata2datetime()等
8. 調整器：firstdayofweek(), lastdayofmonth(), tonext(), toprev()等
9. 丸め：floor(), ceil(), round()（日付の丸め）
10. I/O：DateFormat, @dateformat_str, format(), parse()

**関連システム・外部連携**：Base.Printf（フォーマット出力）、Base.Iterators（範囲操作）。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | ライブラリ機能のため関連画面なし |

## 機能種別

日付・時刻操作ライブラリ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| year, month, day | Int64 | Yes/No | 日付構成要素 | 1 <= month <= 12, 1 <= day <= daysinmonth |
| hour, minute, second | Int64 | No | 時刻構成要素 | 0-23, 0-59, 0-59 |
| millisecond | Int64 | No | ミリ秒 | 0-999 |
| format_string | AbstractString | No | 日付フォーマット文字列 | 有効なDateFormatパターン |

### 入力データソース

- ユーザコードからの直接指定
- 文字列からのパース（`Date("2024-01-01", dateformat"y-m-d")`）
- Unix時刻からの変換

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Date | Date | 日付型（Day精度、UTInstant{Day}） |
| DateTime | DateTime | 日時型（Millisecond精度、UTInstant{Millisecond}） |
| Time | Time | 時刻型（Nanosecond精度） |
| Period | 各Period型 | 期間（Year, Month, Day等） |

### 出力先

Julia値として返却

## 処理フロー

### 処理シーケンス

```
1. 型定義（types.jl）
   ├─ 抽象型階層: AbstractTime → Period/Instant/TimeType
   ├─ DatePeriod型: Year, Quarter, Month, Week, Day
   ├─ TimePeriod型: Hour, Minute, Second, Millisecond, Microsecond, Nanosecond
   ├─ UTInstant{P}: 機械表現（エポックからの期間数）
   └─ Date, DateTime, Time: ユーザ向け型
2. 期間演算（periods.jl）
   ├─ 比較、加算、減算、乗算
   └─ canonicalize: 期間の正規化
3. アクセサ（accessors.jl）
   └─ yearmonthday, year, month, day, hour, minute, second等
4. クエリ（query.jl）
   └─ dayofweek, isleapyear, daysinmonth, dayname等
5. 算術演算（arithmetic.jl）
   └─ Date/DateTime + Period, Date - Date
6. 変換（conversions.jl）
   └─ unix2datetime, datetime2unix, now, today
7. 範囲（ranges.jl）
   └─ Date/DateTime のStepRange対応
8. 調整器（adjusters.jl）
   └─ firstdayofweek, lastdayofmonth, tonext, toprev
9. 丸め（rounding.jl）
   └─ floor, ceil, round（Periodに対する丸め）
10. I/O（io.jl, parse.jl）
    └─ DateFormat, format, parse, @dateformat_str
```

### フローチャート

```mermaid
flowchart TD
    A[ユーザ入力] --> B{入力種別}
    B -->|コンストラクタ| C[Date/DateTime/Time生成]
    B -->|文字列パース| D[parse + DateFormat]
    B -->|Unix時刻| E[unix2datetime]
    C --> F[UTInstant に変換]
    D --> F
    E --> F
    F --> G[内部表現: エポックからのDay/Millisecond数]
    G --> H{操作種別}
    H -->|アクセサ| I[year/month/day等を計算]
    H -->|算術| J[Period加算/減算]
    H -->|フォーマット| K[format → 文字列]
    H -->|クエリ| L[dayofweek/isleapyear等]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-98-01 | 先発グレゴリオ暦 | 全ての日付計算は先発グレゴリオ暦に基づく | 全Date/DateTime操作 |
| BR-98-02 | UT秒ベース | 1日=86400秒（うるう秒を考慮しない） | 全DateTime操作 |
| BR-98-03 | タイムゾーン非対応 | Datesモジュール自体はタイムゾーンを扱わない | TimeZones.jlが別途必要 |
| BR-98-04 | DatePeriod比較制限 | Week(1)==Day(7)は成立するがYear(1)!=Day(365) | DatePeriod比較 |
| BR-98-05 | TimePeriod完全変換 | Hour(1)==Minute(60)==Second(3600)が成立 | TimePeriod比較 |

### 計算ロジック

- エポック: 0000-12-31をratadie日0とする
- Date内部表現: `UTInstant{Day}` - エポックからの日数
- DateTime内部表現: `UTInstant{Millisecond}` - エポックからのミリ秒数
- うるう年判定: `isleapyear(y) = (y % 4 == 0) && (y % 100 != 0 || y % 400 == 0)`

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentError | 無効な日付値（月が13以上等） | エラーメッセージ付きArgumentError |
| - | InexactError | Period変換時の精度損失 | InexactError |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- Date/DateTimeはimmutable structとして実装され、メモリ割り当てが最小化されている
- @dateformat_strマクロによりフォーマット文字列のコンパイル時解析が可能

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

特になし

## 備考

- `now()`は`Libc.time()`を使用してシステム時刻を取得
- `today()`は`now()`からDate部分のみを取得
- CompactPeriod型により期間の効率的な表現が可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.jl | `stdlib/Dates/src/types.jl` | 抽象型階層(AbstractTime, Period, Instant, TimeType)と具象型(Date, DateTime, Time) |

**読解のコツ**: `@eval`マクロでDatePeriod/TimePeriod型が動的に定義されている（52-63行目）。全てのPeriod型は`value::Int64`フィールドを1つ持つ単純な構造体である。DateとDateTimeは`UTInstant{Day}`と`UTInstant{Millisecond}`をラップしている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Dates.jl | `stdlib/Dates/src/Dates.jl` | モジュール定義、include順序、エクスポートリスト |

**主要処理フロー**:
1. **40-51行目**: types.jl → periods.jl → accessors.jl → ... → parse.jl の順にinclude
2. **53-84行目**: エクスポートシンボルの定義

#### Step 3: 期間演算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | periods.jl | `stdlib/Dates/src/periods.jl` | Period同士の比較、加算、canonicalize |

#### Step 4: 算術演算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | arithmetic.jl | `stdlib/Dates/src/arithmetic.jl` | Date/DateTime + Period の演算規則 |

#### Step 5: I/O処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | io.jl | `stdlib/Dates/src/io.jl` | DateFormat型、format関数 |
| 5-2 | parse.jl | `stdlib/Dates/src/parse.jl` | 文字列パース処理 |

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

```
Dates モジュール
    |
    +-- types.jl (型定義)
    |       +-- Period (Year, Month, Day, ...)
    |       +-- UTInstant{P}
    |       +-- Date, DateTime, Time
    |
    +-- periods.jl (期間演算)
    |       +-- +, -, *, ==, <
    |       +-- canonicalize
    |
    +-- accessors.jl (アクセサ)
    |       +-- year, month, day, hour, ...
    |       +-- yearmonthday
    |
    +-- query.jl (クエリ)
    |       +-- dayofweek, isleapyear, daysinmonth
    |       +-- dayname, monthname
    |
    +-- arithmetic.jl (算術演算)
    |       +-- Date/DateTime + Period
    |       +-- Date - Date
    |
    +-- conversions.jl (変換)
    |       +-- unix2datetime, datetime2unix
    |       +-- now, today
    |
    +-- io.jl + parse.jl (I/O)
            +-- DateFormat, format, parse
            +-- @dateformat_str
```

### データフロー図

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

年/月/日/時/分/秒 ────────> Date/DateTime コンストラクタ ──> UTInstant内部表現
                                |
日付文字列 ────────────────> parse(str, DateFormat) ───────> Date/DateTime
                                |
Unix時刻 ──────────────────> unix2datetime ────────────────> DateTime
                                |
Date/DateTime ─────────────> format(dt, DateFormat) ──────> 文字列
                                |
Date + Period ─────────────> arithmetic演算 ───────────────> Date/DateTime
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Dates.jl | `stdlib/Dates/src/Dates.jl` | ソース | モジュール定義・エクスポート |
| types.jl | `stdlib/Dates/src/types.jl` | ソース | 型定義 |
| periods.jl | `stdlib/Dates/src/periods.jl` | ソース | 期間演算 |
| accessors.jl | `stdlib/Dates/src/accessors.jl` | ソース | アクセサ関数 |
| query.jl | `stdlib/Dates/src/query.jl` | ソース | クエリ関数 |
| arithmetic.jl | `stdlib/Dates/src/arithmetic.jl` | ソース | 算術演算 |
| conversions.jl | `stdlib/Dates/src/conversions.jl` | ソース | 変換関数 |
| ranges.jl | `stdlib/Dates/src/ranges.jl` | ソース | 日付範囲 |
| adjusters.jl | `stdlib/Dates/src/adjusters.jl` | ソース | 調整器関数 |
| rounding.jl | `stdlib/Dates/src/rounding.jl` | ソース | 丸め関数 |
| io.jl | `stdlib/Dates/src/io.jl` | ソース | フォーマット出力 |
| parse.jl | `stdlib/Dates/src/parse.jl` | ソース | 文字列パース |
| deprecated.jl | `stdlib/Dates/src/deprecated.jl` | ソース | 非推奨関数 |
