---
generated_at: 2026-02-22 12:00:00
metrics:
  claims_total: 145
  claims_with_evidence: 139
  claims_without_evidence: 6
confidence_derived: 0.96
---

# 根拠レポート：mruby-time 単体テストケース一覧

## 本レポートについて

### 目的
本レポートは、生成された設計書・ドキュメントの信頼性を検証し、人間レビュアーが効率的にレビューできるようにすることを目的としています。

### チェック方法
以下の観点でドキュメントの内容（Claim：主張）を検証しています：

1. **根拠の有無確認**：各主張に対して、ソースコード・既存設計書・要件定義書などの根拠（Evidence）が存在するか
2. **根拠との整合性**：主張の内容が根拠と矛盾していないか
3. **網羅性**：参照すべき情報源を適切にカバーしているか

### 信頼度スコアの算出
- **confidence_derived** = 根拠あり件数 / 総主張件数
- 状態「○」：根拠あり、「△」：根拠不足または要確認

### 本レポートの使い方
1. まず「サマリー」で全体の信頼度と優先レビュー項目を確認
2. 「Claims と根拠の対応」で △ の項目を重点的にレビュー
3. 「不足情報」で補完が必要な情報源を確認

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**0.96**
  - 根拠あり：139 / 145、根拠なし：6
- 優先レビュー（高）
  1. **C-101 (Time#dst? ローカル時刻)**: DST判定はOS/タイムゾーンに依存し、ソースコードからのみでは期待結果を確定できない
  2. **C-099 (Time#zone ローカル時刻)**: タイムゾーンオフセット文字列はプラットフォーム依存
  3. **C-130 (time_value_from_time_t 大きな値)**: MRB_USE_BIGINTとMRB_NO_FLOATのコンパイル条件により動作が異なる

## 2) 参照した情報（Evidence一覧）
> ここに「実在するもの」だけ列挙。

- E-01: `mrbgems/mruby-time/src/time.c` (メインソースファイル、1740行)
- E-02: `mrbgems/mruby-time/include/mruby/time.h` (公開ヘッダファイル、27行)
- E-03: `mrbgems/mruby-time/test/time.rb` (既存テストコード、313行)
- E-04: `mrbgems/mruby-time/mrbgem.rake` (gem定義ファイル)
- E-05: ISO 15.2.19 (Rubyの組み込みTimeクラス仕様、ソースコードのコメントから参照)

## 3) Claims と根拠の対応（レビューの主戦場）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-001 | Time.nowが現在時刻のTimeオブジェクトを返す | E-01 (L599-603: time_now関数), E-03 (L57-59) | ○ |
| C-002 | Time.nowがローカルタイムゾーンで生成される | E-01 (L584: MRB_TIMEZONE_LOCAL設定) | ○ |
| C-003 | Time.at(seconds)で指定秒数のTimeオブジェクトが生成される | E-01 (L635-644: time_at_m関数), E-03 (L12-22) | ○ |
| C-004 | Time.at(seconds, microseconds)でマイクロ秒付き生成 | E-01 (L641: mrb_get_argsの"o\|o"), E-03 (L255-257) | ○ |
| C-005 | Time.at(0)でUnixエポック生成 | E-01 (L635-644), E-05 (ISO定義) | ○ |
| C-006 | Time.atにFloat値でマイクロ秒精度生成 | E-01 (L289-312: mrb_time_t_from_float), E-03 (L13) | ○ |
| C-007 | Time.atにFloat::NANでFloatDomainError | E-01 (L295: mrb_check_num_exact), E-03 (L16) | ○ |
| C-008 | Time.atにFloat::INFINITYでFloatDomainError | E-01 (L295-298), E-03 (L17) | ○ |
| C-009 | Time.atに-Float::INFINITYでFloatDomainError | E-01 (L295-298), E-03 (L18) | ○ |
| C-010 | Time.atの第2引数にFloat::NANでFloatDomainError | E-01 (L491: mrb_to_time_t), E-03 (L19) | ○ |
| C-011 | Time.atにTime範囲外でRangeError | E-01 (L276-279: time_out_of_range) | ○ |
| C-012 | Time.atに不正な型でTypeError | E-01 (L373: mrb_raisef TypeError) | ○ |
| C-013 | Time.gm(year, month, day)でUTC時刻生成 | E-01 (L732-741: time_gm関数), E-03 (L24-33) | ○ |
| C-014 | Time.gm(year)でデフォルト値使用 | E-01 (L735: デフォルト値定義), E-03 (L61-70) | ○ |
| C-015 | Time.gm全7引数で正しいTimeオブジェクト | E-01 (L737: mrb_get_argsの"i\|iiiiii") | ○ |
| C-016 | Time.gm月=0でArgumentError | E-01 (L672: amonth < 1チェック) | ○ |
| C-017 | Time.gm月=13でArgumentError | E-01 (L672: amonth > MONTHS_PER_YEARチェック) | ○ |
| C-018 | Time.gm日=0でArgumentError | E-01 (L673: aday < 1チェック) | ○ |
| C-019 | Time.gm日=32でArgumentError | E-01 (L673: aday > 31チェック) | ○ |
| C-020 | Time.gm時=25でArgumentError | E-01 (L674: ahour > HOURS_PER_DAYチェック) | ○ |
| C-021 | Time.gm分=60でArgumentError | E-01 (L676: amin > MINS_PER_HOUR-1チェック) | ○ |
| C-022 | Time.gm秒=61でArgumentError | E-01 (L677: asec > SECS_PER_MINチェック) | ○ |
| C-023 | Time.gm秒=60(閏秒)が正常処理 | E-01 (L677: asec > 60で弾くので60は通る) | ○ |
| C-024 | Time.gm時=24:00:00が正常処理 | E-01 (L675: ahour==24 && amin==0 && asec==0は通る) | ○ |
| C-025 | Time.gm時=24:01でArgumentError | E-01 (L675: ahour==24 && amin>0でエラー) | ○ |
| C-026 | Time.utcがTime.gmと同じ動作 | E-01 (L1731: utcはtime_gmを参照), E-03 (L61-70) | ○ |
| C-027 | Time.local(year, month, day, hour)でローカル時刻生成 | E-01 (L758-767: time_local関数), E-03 (L35-44) | ○ |
| C-028 | Time.local全7引数でマイクロ秒付きTimeオブジェクト | E-01 (L761-766), E-03 (L46-55) | ○ |
| C-029 | Time.mktimeがTime.localと同じ動作 | E-01 (L1729: mktimeはtime_localを参照), E-03 (L46-55) | ○ |
| C-030 | Time.new(引数なし)で現在時刻生成 | E-01 (L1216-1240: time_init), E-03 (L4-6) | ○ |
| C-031 | Time.new(year, month, day, hour, min, sec)でローカル時刻生成 | E-01 (L1234-1236: time_mktime呼び出し) | ○ |
| C-032 | Time.new(year)でデフォルト値使用 | E-01 (L1219-1220: デフォルト値定義) | ○ |
| C-033 | Time#dupで正しくコピー | E-01 (L1252-1273: time_init_copy), E-03 (L163-166) | ○ |
| C-034 | initialize_copyに異なるクラスでTypeError | E-01 (L1258-1260: mrb_obj_is_instance_ofチェック) | ○ |
| C-035 | initialize_copyに未初期化TimeでArgumentError | E-01 (L1264-1265: time_uninitializedチェック) | ○ |
| C-036 | 同じ時刻のTime ==でtrue | E-01 (L800-809: time_eq), E-03 (L96-105: <=>テストから推測) | ○ |
| C-037 | 異なる時刻のTime ==でfalse | E-01 (L806: sec==sec && nsec==nsecの比較) | ○ |
| C-038 | ナノ秒が異なるTime ==でfalse | E-01 (L806: nsec比較), E-03 (L265) | ○ |
| C-039 | Time以外と==でfalse | E-01 (L805: DATA_CHECK_GET_PTRがNULLを返す) | ○ |
| C-040 | eql?が==と同じ結果 | E-01 (L1669-1670: 同じtime_eq関数) | ○ |
| C-041 | <=>で-1 | E-01 (L825-847: time_cmp), E-03 (L96-105) | ○ |
| C-042 | <=>で0 | E-01 (L846), E-03 (L102) | ○ |
| C-043 | <=>で1 | E-01 (L833-835), E-03 (L101) | ○ |
| C-044 | ナノ秒差での<=> | E-01 (L840-845: nsec比較) | ○ |
| C-045 | Time以外と<=>でnil | E-01 (L832: !tm2ならnil), E-03 (L104) | ○ |
| C-046 | Time#+(整数)で加算 | E-01 (L867-898: time_plus), E-03 (L72-82) | ○ |
| C-047 | Time#+(Float)でマイクロ秒精度加算 | E-01 (L870-874: mrb_to_time_tのFloat変換) | ○ |
| C-048 | +で元のオブジェクトが不変 | E-01 (L897: 新しいtime_make_time) | ○ |
| C-049 | +でオーバーフロー時RangeError | E-01 (L881-894: int_overflow) | ○ |
| C-050 | +(Float::NAN)でFloatDomainError | E-01 (L870: mrb_to_time_t), E-03 (L79) | ○ |
| C-051 | +(Float::INFINITY)でFloatDomainError | E-01 (L870: mrb_to_time_t), E-03 (L80) | ○ |
| C-052 | Time#-(整数)で減算 | E-01 (L914-960: time_minus), E-03 (L84-94) | ○ |
| C-053 | Time#-(Time)でFloat差分 | E-01 (L921-931: Time同士の減算), E-03 (L84-94) | ○ |
| C-054 | Time#-(Time)でナノ秒精度差分 | E-01 (L924-925: nsec差分計算) | ○ |
| C-055 | -でアンダーフロー時RangeError | E-01 (L942-955: int_overflow) | ○ |
| C-056 | -(Float::NAN)でFloatDomainError | E-01 (L935: mrb_to_time_t), E-03 (L91) | ○ |
| C-057 | Time#yearが正しい年を返す | E-01 (L1005-1010: time_year), E-03 (L277-279) | ○ |
| C-058 | Time.at(0).yearが1970 | E-01 (L1009: tm_year + TM_YEAR_BASE) | ○ |
| C-059 | Time#monが正しい月を返す | E-01 (L1323-1328: time_mon), E-03 (L185-187) | ○ |
| C-060 | Time#monthがmonと同じ | E-01 (L1690: monthとmonが同じ実装), E-03 (L189-191) | ○ |
| C-061 | Time#dayが正しい日を返す | E-01 (L1109-1114: time_day), E-03 (L115-117) | ○ |
| C-062 | Time#mdayがdayと同じ | E-01 (L1687: mdayとdayが同じ実装), E-03 (L177-179) | ○ |
| C-063 | Time#hourが正しい時を返す | E-01 (L1195-1200: time_hour), E-03 (L156-158) | ○ |
| C-064 | Time#minが正しい分を返す | E-01 (L1306-1311: time_min), E-03 (L181-183) | ○ |
| C-065 | Time#secが正しい秒を返す | E-01 (L1341-1346: time_sec), E-03 (L193-195) | ○ |
| C-066 | Time#usecがマイクロ秒を返す | E-01 (L1397-1402: time_usec), E-03 (L255-257) | ○ |
| C-067 | usecなしでTime#usecが0 | E-01 (L1401: nsec/NSECS_PER_USEC), E-03 (L207) | ○ |
| C-068 | Time#nsecがナノ秒を返す | E-01 (L1415-1420: time_nsec), E-03 (L255-256) | ○ |
| C-069 | tv_nsecがnsecと同じ | E-01 (L1695: tv_nsecとnsecが同じ実装), E-03 (L247-248) | ○ |
| C-070 | nsecが0-999999999の範囲 | E-01 (L453-471: 正規化ロジック), E-03 (L251-252) | ○ |
| C-071 | usec == nsec/1000 | E-01 (L1401 vs L1419), E-03 (L260) | ○ |
| C-072 | Time#wdayが正しい曜日を返す | E-01 (L972-977: time_wday), E-03 (L269-271) | ○ |
| C-073 | Time#ydayが正しい年日を返す | E-01 (L989-994: time_yday), E-03 (L273-275) | ○ |
| C-074 | 年初のydayが1 | E-01 (L993: tm_yday+1) | ○ |
| C-075 | 非閏年年末のydayが365 | E-01 (L993: tm_yday+1) | ○ |
| C-076 | 閏年年末のydayが366 | E-01 (L993: tm_yday+1) | ○ |
| C-077 | Time#to_iが整数で返す | E-01 (L1380-1385: time_to_i), E-03 (L202-204) | ○ |
| C-078 | Time.at(0).to_iが0 | E-01 (L1384: time_value_from_time_t) | ○ |
| C-079 | Time#to_fがFloatで返す | E-01 (L1361-1367: time_to_f), E-03 (L197-200) | ○ |
| C-080 | Time#to_fがナノ秒精度を含む | E-01 (L1365: nsec/1.0e9) | ○ |
| C-081 | UTC時刻のutc?がtrue | E-01 (L1454-1459: time_utc_p), E-03 (L218-220) | ○ |
| C-082 | ローカル時刻のutc?がfalse | E-01 (L1458: timezone == MRB_TIMEZONE_UTC) | ○ |
| C-083 | gmt?がutc?と同じ結果 | E-01 (L1683, L1697: 同じ実装), E-03 (L140-142) | ○ |
| C-084 | Time#utcがUTCに変更してselfを返す | E-01 (L1434-1441: time_utc), E-03 (L212-216) | ○ |
| C-085 | Time#gmtimeがTime#utcと同じ | E-01 (L1684: gmtimeはtime_utcを参照), E-03 (L147-151) | ○ |
| C-086 | Time#localtimeがローカルに変更してselfを返す | E-01 (L1286-1293: time_localtime), E-03 (L168-175) | ○ |
| C-087 | Time#localtimeでsec値は不変 | E-01 (L1290-1291: timezoneとdatetimeのみ変更) | ○ |
| C-088 | Time#getutcが新しいUTC Timeを返す | E-01 (L1148-1159: time_getutc), E-03 (L136-138) | ○ |
| C-089 | Time#getutcで元オブジェクト不変 | E-01 (L1152-1153: 新しいmrb_time構造体をmalloc) | ○ |
| C-090 | Time#getgmがgetutcと同じ | E-01 (L1680, L1682: 同じ実装), E-03 (L123-125) | ○ |
| C-091 | Time#getlocalが新しいローカルTimeを返す | E-01 (L1172-1183: time_getlocal), E-03 (L127-134) | ○ |
| C-092 | Time#getlocalで元オブジェクト不変 | E-01 (L1176-1177: 新しいmrb_time構造体をmalloc) | ○ |
| C-093 | Time#asctimeの正しいフォーマット | E-01 (L1073-1097: time_asctime), E-03 (L107-109) | ○ |
| C-094 | Time#ctimeがasctimeと同じ | E-01 (L1677: ctimeはtime_asctimeを参照), E-03 (L111-113) | ○ |
| C-095 | UTC時刻のto_sフォーマット | E-01 (L1472-1495: time_to_s), E-03 (L287-289) | ○ |
| C-096 | ローカル時刻のto_sフォーマット | E-01 (L1482-1491), E-03 (L291-294) | ○ |
| C-097 | inspectがto_sと同じ | E-01 (L1675: inspectはtime_to_sを参照), E-03 (L291-294) | ○ |
| C-098 | UTC時刻のzoneが"UTC" | E-01 (L1050-1060: time_zone), E-03 (L281-283) | ○ |
| C-099 | ローカル時刻のzoneがオフセット文字列 | E-01 (L1057-1059: time_zonename呼び出し) | △ |
| C-100 | UTC時刻のdst?がfalse | E-01 (L1129-1134: time_dst_p), E-03 (L119-121) | ○ |
| C-101 | ローカル時刻のdst?がtm_isdstに基づく | E-01 (L1133: tm_isdst参照) | △ |
| C-102 | 同じ時刻のhash値が一致 | E-01 (L1508-1516: time_hash) | ○ |
| C-103 | 異なる時刻のhash値が異なる（高確率） | E-01 (L1512-1514: mrb_byte_hash使用) | △ |
| C-104 | sunday?が日曜日でtrue | E-01 (L1537-1541: time_sunday), E-03 (L296-305) | ○ |
| C-105 | sunday?が日曜日以外でfalse | E-01 (L1540: wday_p(0)), E-03 (L298) | ○ |
| C-106 | monday?が月曜日でtrue | E-01 (L1553-1556), E-03 (L299) | ○ |
| C-107 | tuesday?が火曜日でtrue | E-01 (L1568-1571), E-03 (L300) | ○ |
| C-108 | wednesday?が水曜日でtrue | E-01 (L1583-1586), E-03 (L301) | ○ |
| C-109 | thursday?が木曜日でtrue | E-01 (L1598-1601), E-03 (L302) | ○ |
| C-110 | friday?が金曜日でtrue | E-01 (L1613-1616), E-03 (L303) | ○ |
| C-111 | saturday?が土曜日でtrue | E-01 (L1628-1631), E-03 (L304) | ○ |
| C-112 | UTCのutc_offsetが0 | E-01 (L1650-1664: time_utc_offset), E-03 (L225) | ○ |
| C-113 | ローカルのutc_offsetが整数で返る | E-01 (L1660-1663), E-03 (L229) | ○ |
| C-114 | utc_offsetが900の倍数 | E-03 (L232) | ○ |
| C-115 | gmt_offsetがutc_offsetと同じ | E-01 (L1711), E-03 (L235-237) | ○ |
| C-116 | gmtoffがutc_offsetと同じ | E-01 (L1712), E-03 (L236-238) | ○ |
| C-117 | 4で割り切れる年がうるう年 | E-01 (L184-188: is_leapyear) | ○ |
| C-118 | 100で割り切れる年がうるう年でない | E-01 (L187: y%100!=0) | ○ |
| C-119 | 400で割り切れる年がうるう年 | E-01 (L187: y%400==0) | ○ |
| C-120 | 4で割り切れない年がうるう年でない | E-01 (L187: y%4==0の条件) | ○ |
| C-121 | timegmで1970-01-01がtime_t=0 | E-01 (L190-221: timegm実装) | ○ |
| C-122 | 1970年前が負のtime_t | E-01 (L207-210: 負の方向の計算) | ○ |
| C-123 | うるう年2月29日が正しく計算 | E-01 (L193-196: ndays配列, L200: is_leapyear参照) | ○ |
| C-124 | 正のナノ秒オーバーフロー正規化 | E-01 (L466-471: nsec >= 1000000000Lの処理) | ○ |
| C-125 | 負のナノ秒正規化 | E-01 (L455-464: nsec < 0の処理) | ○ |
| C-126 | マイクロ秒オーバーフロー正規化 | E-01 (L494-498: tusec正規化) | ○ |
| C-127 | fixable_time_t_pが範囲内でTRUE | E-01 (L265-273: fixable_time_t_p) | ○ |
| C-128 | fixable_time_t_pが範囲外でFALSE | E-01 (L269: v > MRB_INT_MAXでFALSE) | ○ |
| C-129 | time_value_from_time_tがmrb_int_valueで返る | E-01 (L385-403: time_value_from_time_t) | ○ |
| C-130 | 大きな値がBigInt/Floatで返る | E-01 (L389-401: コンパイル条件分岐) | △ |
| C-131 | mrb_time_atが正しいTimeオブジェクトを返す | E-01 (L605-619: mrb_time_at), E-02 (L22) | ○ |
| C-132 | mrb_time_atのusec正規化 | E-01 (L611-615: usec正規化) | ○ |
| C-133 | mrb_time_get_tmがstruct tmポインタを返す | E-01 (L779-785: mrb_time_get_tm), E-02 (L23) | ○ |
| C-134 | 未初期化Timeでmrb_time_get_tmがArgumentError | E-01 (L772-776: time_get_ptr) | ○ |
| C-135 | 2000回の0.5ms加算で1秒 | E-03 (L307-313: テストケースが存在) | ○ |
| C-136 | mktime/timegmが-1を返した場合のエラー検出 | E-01 (L707-714: nowsecs==-1の分岐) | ○ |
| C-137 | エポック1秒前の正常処理 | E-01 (L708-713: test_tmで+1sec検証) | ○ |
| C-138 | 年のアンダーフローでArgumentError | E-01 (L660-661: MRB_INT_MIN + TM_YEAR_BASEチェック) | ○ |
| C-139 | UTCでgmtime_r使用 | E-01 (L414-415: timezone==UTC分岐) | ○ |
| C-140 | ローカルでlocaltime_r使用 | E-01 (L417-418: else分岐) | ○ |
| C-141 | gmtime_r/localtime_rがNULLでRangeError | E-01 (L420-423: !aidチェック) | ○ |
| C-142 | gem初期化でTimeクラス定義 | E-01 (L1719-1734: mrb_mruby_time_gem_init) | ○ |
| C-143 | Comparableモジュールinclude | E-01 (L1725: mrb_include_module) | ○ |
| C-144 | クラスメソッドの定義 | E-01 (L1726-1731: mrb_define_class_method_id) | ○ |
| C-145 | mrb_timezone enumの定義 | E-02 (L15-20: enum mrb_timezone) | ○ |

## 4) 不足情報（Unknown / Missing）
- **C-099**: ローカルタイムゾーンのzone文字列はプラットフォーム固有のstrftime("%z")に依存するため、特定の期待結果を定義できない
  - 候補：各プラットフォームでの実行テスト / CI環境でのタイムゾーン固定
- **C-101**: DST(夏時間)の判定はOSのタイムゾーンデータベースに依存する。テスト環境によって結果が異なる
  - 候補：タイムゾーンを固定した環境でのテスト / UTCのみの検証で確認済み(C-100)
- **C-103**: ハッシュ値の非一致は確率的であり、保証できない（ハッシュ衝突の可能性あり）
  - 候補：テスト削除 / 多数のサンプルで衝突率を統計的に検証
- **C-130**: MRB_USE_BIGINTとMRB_NO_FLOATのコンパイル条件によって動作が3パターンに分岐する
  - 候補：各コンパイル条件でのビルド・テスト実行
- **C-099, C-101のゾーン/DST関連**: mruby-time/test/time.rbでもDSTとzoneのローカル詳細テストは簡略化されている
  - 候補：テスト環境のタイムゾーン固定 (TZ=UTC等)
- **Windows固有のgettimeofday実装**: `MRB_TIME_WINDOWS_NO_STRFTIME_Z`やWindows polyfillの検証はWindowsビルド環境が必要
  - 候補：Windows CI環境 / クロスコンパイルテスト

## 5) リスクフラグ（レビュー観点）
- 0: 低リスク - 大部分のテストケースはソースコード内の関数定義・バリデーション・ISO仕様コメントに直接紐付けられており、信頼性が高い
- 1: 中リスク - プラットフォーム依存機能（DST判定、タイムゾーン文字列、Windows固有実装）のテストは実行環境に依存する
- 1: 中リスク - コンパイル条件分岐（MRB_NO_FLOAT, MRB_USE_BIGINT, USE_SYSTEM_TIMEGM）により一部テストケースは特定ビルド構成でのみ有効

## 6) レビュアーチェックリスト（最小）
- [ ] Time.at, Time.gm, Time.local, Time.now, Time.utc, Time.mktimeの全クラスメソッドがテストされているか
- [ ] 全インスタンスメソッド（year, month, day, hour, min, sec, usec, nsec, wday, yday, zone, to_s, to_i, to_f, asctime, utc?, dst?, hash, <=>，==, +, -等）がカバーされているか
- [ ] エイリアスメソッド（ctime/asctime, month/mon, mday/day, gmt?/utc?, getgm/getutc, gmtime/utc, gmt_offset/utc_offset/gmtoff）が正しくテストされているか
- [ ] 境界値テスト（閏秒sec=60, 24:00:00, 閏年2月29日, ydayの年初年末）が含まれているか
- [ ] 異常系テスト（NaN, Infinity, 型エラー, 範囲外エラー, 未初期化オブジェクト）が含まれているか
- [ ] 内部関数（is_leapyear, timegm, time_alloc_time, fixable_time_t_p）の単体テストが含まれているか
- [ ] C API（mrb_time_at, mrb_time_get_tm）のテストが含まれているか
- [ ] プラットフォーム依存テストケース（C-099, C-101, C-130）について実行環境の制約が明記されているか
