# 機能設計書 29-日付・時刻関数

## 概要

本ドキュメントは、SQLiteの日付・時刻関数（date.c）の機能設計を記述する。これらの関数は日付と時刻の計算、フォーマット、変換を行う機能を提供する。

### 本機能の処理概要

日付・時刻関数は、内部的にユリウス日（Julian Day Number）を使用して日付計算を行い、様々なフォーマットでの入出力をサポートする。

**業務上の目的・背景**：アプリケーション開発において日付・時刻の操作は頻繁に必要となる。SQLiteの日付関数により、データベースクエリ内で直接日付計算やフォーマット変換が可能となり、アプリケーションコードの簡素化と処理効率の向上を実現する。

**機能の利用シーン**：
- 現在日時の取得
- 日付の加算・減算
- 異なるフォーマット間の変換
- タイムゾーン処理
- 曜日・週番号の計算

**主要な処理内容**：
1. ユリウス日への変換
2. 各種修飾子（modifier）による日付計算
3. フォーマット文字列に基づく出力整形
4. ローカルタイム/UTC変換

**関連システム・外部連携**：OSのlocaltime()/gmtime()関数を使用してタイムゾーン処理を行う。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | CLIメイン | 主機能 | 日付クエリ実行 |

## 機能種別

SQL関数 / 日付・時刻処理

## 入力仕様

### 入力パラメータ

| 関数名 | 引数 | 説明 |
|--------|-----|------|
| date(timevalue, modifier...) | TEXT | 日付を'YYYY-MM-DD'形式で返却 |
| time(timevalue, modifier...) | TEXT | 時刻を'HH:MM:SS'形式で返却 |
| datetime(timevalue, modifier...) | TEXT | 日時を'YYYY-MM-DD HH:MM:SS'形式で返却 |
| julianday(timevalue, modifier...) | REAL | ユリウス日を返却 |
| unixepoch(timevalue, modifier...) | INT | Unix時間を返却 |
| strftime(format, timevalue, modifier...) | TEXT | フォーマット指定で返却 |

### 対応時刻フォーマット

| フォーマット | 例 | 説明 |
|------------|-----|------|
| YYYY-MM-DD | 2024-01-15 | ISO 8601日付 |
| YYYY-MM-DD HH:MM | 2024-01-15 10:30 | 日時（秒なし） |
| YYYY-MM-DD HH:MM:SS | 2024-01-15 10:30:45 | 日時 |
| YYYY-MM-DD HH:MM:SS.SSS | 2024-01-15 10:30:45.123 | ミリ秒付き |
| YYYY-MM-DDTHH:MM:SS | 2024-01-15T10:30:45 | ISO 8601形式（T区切り） |
| HH:MM | 10:30 | 時刻のみ |
| HH:MM:SS | 10:30:45 | 時刻（秒付き） |
| now | - | 現在時刻 |
| DDDDDDDDDD | 2440587.5 | ユリウス日 |

### 修飾子（Modifier）

| 修飾子 | 例 | 説明 |
|--------|-----|------|
| NNN days | +7 days | 日数加算 |
| NNN hours | -2 hours | 時間加算 |
| NNN minutes | +30 minutes | 分加算 |
| NNN seconds | +45 seconds | 秒加算 |
| NNN months | +1 months | 月加算 |
| NNN years | -1 years | 年加算 |
| start of month | - | 月初へ |
| start of year | - | 年初へ |
| start of day | - | 日初へ |
| weekday N | weekday 0 | 次の曜日（0=日曜） |
| localtime | - | ローカルタイムへ変換 |
| utc | - | UTCへ変換 |
| subsec/subsecond | - | サブ秒精度を有効化 |

## 出力仕様

### 出力データ

| 関数 | 戻り値型 | 例 |
|------|----------|-----|
| date | TEXT | '2024-01-15' |
| time | TEXT | '10:30:45' |
| datetime | TEXT | '2024-01-15 10:30:45' |
| julianday | REAL | 2460324.9380... |
| unixepoch | INTEGER | 1705311045 |
| strftime | TEXT | フォーマット依存 |

### 出力先

- クエリ結果として返却

## 処理フロー

### 処理シーケンス

```
1. 入力解析
   └─ 時刻文字列/ユリウス日/Unix時間を解析

2. DateTime構造体へ変換
   └─ validJD, validYMD, validHMSフラグ設定

3. 修飾子適用
   └─ 各修飾子を順次適用

4. 出力変換
   └─ 要求形式に変換して返却
```

### フローチャート

```mermaid
flowchart TD
    A[時刻入力] --> B{入力形式判定}
    B -->|YYYY-MM-DD| C[parseYyyyMmDd]
    B -->|HH:MM:SS| D[parseHhMmSs]
    B -->|Julian Day| E[parseJulianDay]
    B -->|Unix epoch| F[parseUnixEpoch]
    B -->|now| G[setDateTimeToCurrent]
    C --> H[DateTime構造体]
    D --> H
    E --> H
    F --> H
    G --> H
    H --> I{修飾子あり?}
    I -->|Yes| J[parseModifier]
    I -->|No| K[出力変換]
    J --> L{次の修飾子?}
    L -->|Yes| J
    L -->|No| K
    K --> M[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-29-01 | ユリウス日基準 | 内部計算はユリウス日で行う | 常時 |
| BR-29-02 | グレゴリオ暦 | 全日付はグレゴリオ暦として扱う | 常時 |
| BR-29-03 | 年範囲 | 0000-01-01 〜 9999-12-31 | 常時 |
| BR-29-04 | ミリ秒丸め | 0.999を超えるミリ秒は0.999に丸める | サブ秒処理時 |
| BR-29-05 | タイムゾーン | デフォルトはUTC | localtime未指定時 |

### 計算ロジック

**ユリウス日計算（computeJD関数）**:
```c
// Meeus, Astronomical Algorithms, 2nd Edition より
if (M <= 2) { Y--; M += 12; }
A = (Y + 4800) / 100;
B = 38 - A + (A / 4);
X1 = 36525 * (Y + 4716) / 100;
X2 = 306001 * (M + 1) / 10000;
iJD = (X1 + X2 + D + B - 1524.5) * 86400000;
```

**strftimeフォーマット指定子**:
| 指定子 | 説明 | 例 |
|--------|------|-----|
| %Y | 4桁年 | 2024 |
| %m | 2桁月（01-12） | 01 |
| %d | 2桁日（01-31） | 15 |
| %H | 2桁時（00-23） | 10 |
| %M | 2桁分（00-59） | 30 |
| %S | 2桁秒（00-59） | 45 |
| %f | 秒＋ミリ秒 | 45.123 |
| %j | 年間通日（001-366） | 015 |
| %w | 曜日（0-6、0=日曜） | 1 |
| %W | 週番号（00-53） | 03 |
| %s | Unix時間 | 1705311045 |
| %J | ユリウス日 | 2460324.9380 |
| %% | リテラル% | % |

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

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

日付・時刻関数はデータベースを直接変更しない（読み取り専用）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NULL返却 | 解析エラー | 無効な日時文字列 | 正しいフォーマットを使用 |
| NULL返却 | オーバーフロー | 年範囲外（<-4713 or >9999） | 範囲内の日付を使用 |
| NULL返却 | 変換エラー | 無効な修飾子 | 正しい修飾子を使用 |

### リトライ仕様

特になし。

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

- 日付・時刻関数はトランザクション状態に依存しない
- 'now'は非決定的だが、同一ステートメント内では一定

## パフォーマンス要件

- 基本的な日付変換: O(1)
- strftime: フォーマット文字列長に比例

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

- localtime()はOSのタイムゾーン設定に依存
- 大量の修飾子適用でスタックオーバーフローの可能性（通常使用では問題なし）

## 備考

- SQLITE_OMIT_DATETIME_FUNCSでコンパイル時に無効化可能
- ユリウス日のエポックは紀元前4714年11月24日正午（グレゴリオ暦）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | date.c | `src/date.c` | DateTime構造体（66-82行目） |

**読解のコツ**:
- iJD: ユリウス日×86400000（ミリ秒単位）
- Y, M, D: 年月日（validYMD=1のとき有効）
- h, m, s: 時分秒（validHMS=1のとき有効）
- tz: タイムゾーンオフセット（分）
- validJD/validYMD/validHMS: 各フィールドの有効フラグ

#### Step 2: 入力解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | date.c | `src/date.c` | getDigits()関数（112-148行目） |
| 2-2 | date.c | `src/date.c` | parseTimezone()関数（166-198行目） |
| 2-3 | date.c | `src/date.c` | parseHhMmSs()関数（207-244行目） |

**主要処理フロー**:
- **112-148行目**: getDigits - フォーマット文字列に従って数値を抽出
- **166-198行目**: parseTimezone - +/-HH:MM形式またはZ（Zulu）を解析
- **207-244行目**: parseHhMmSs - HH:MM:SS.SSS形式を解析

#### Step 3: ユリウス日計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | date.c | `src/date.c` | computeJD()関数（260-298行目） |

**主要処理フロー**:
- **260-298行目**: computeJD - Y, M, DからiJDを計算（Meeusのアルゴリズム）

#### Step 4: 修飾子処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | date.c | `src/date.c` | parseModifier()関数 |

**修飾子処理**:
- "NNN days/hours/minutes/seconds": iJDへの加算
- "start of month/year/day": 切り捨て処理
- "weekday N": 次の曜日を計算
- "localtime/utc": タイムゾーン変換

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

```
dateFunc()/timeFunc()/datetimeFunc()
    │
    └─ isDate()
           │
           ├─ 入力解析
           │      ├─ parseDateOrTime()
           │      │      ├─ parseYyyyMmDd()
           │      │      └─ parseHhMmSs()
           │      │
           │      └─ setDateTimeToCurrent() ["now"の場合]
           │
           └─ 修飾子ループ
                  └─ parseModifier()
                         ├─ computeJD()
                         ├─ computeYMD()
                         └─ computeHMS()

strftimeFunc()
    │
    ├─ isDate() [上記と同様]
    │
    └─ strftimeループ
           └─ フォーマット指定子処理
```

### データフロー図

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

時刻文字列 ──────────▶ parseDateOrTime()
                            │
                    DateTime構造体
                            │
                    ┌───────┴───────┐
                    │               │
              修飾子あり        修飾子なし
                    │               │
              parseModifier() ──────┘
                            │
                    computeJD() [必要に応じて]
                            │
                    computeYMD() [必要に応じて]
                            │
                    computeHMS() [必要に応じて]
                            │
                            ▼
                    出力変換
                            │
                    ┌───────┴───────┐
                    │       │       │
                  date   time  datetime/strftime
                    │       │       │
                    ▼       ▼       ▼
              'YYYY-MM-DD' 'HH:MM:SS' フォーマット
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| date.c | `src/date.c` | ソース | 日付・時刻関数主実装 |
| func.c | `src/func.c` | ソース | 関数登録 |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダ | 内部定義 |
