TimeZone#strptime がサブ秒を保持できるように修正

rails/rails

ActiveSupport::TimeZone#strptime がエポック秒フォーマットにサブ秒が含まれる場合に小数部を失っていたバグを修正し、Ruby 標準の Time.strptime と同等の精度を提供するようになりました。

背景

ActiveSupport::TimeZone#strptime は文字列を指定フォーマットで解析し Time オブジェクトを生成しますが、"%s.%N" や "%s.%L" のようにエポック秒にサブ秒が付随するケースでサブ秒が常に 0 になる問題がありました。具体例として zone.strptime("1577836800.123456789", "%s.%N").nsec が 0 になる一方、Time.strptime では正しく 123456789 が返ります。この不一致は parts_to_time の実装が :sec_fraction を無視したことが根本原因です。

技術的な変更

修正は activesupport/lib/active_support/values/time_zone.rb の parts_to_time メソッドの :seconds ブランチに sec_fraction を加算 するだけのシンプルな差分です。変更前は time = Time.at(parts[:seconds]) で秒のみを渡していましたが、変更後は time = Time.at(parts[:seconds] + parts.fetch(:sec_fraction, 0)) とし、parts[:sec_fraction] が存在すれば秒に加算して時間を生成します。これにより %s.%N 形式の文字列でもナノ秒単位が保持され、既存の整数秒形式 (%s) やミリ秒形式 (%Q) に影響はありません。

修正の検証として activesupport/test/time_zone_test.rb に新しいテスト test_strptime_with_timestamp_seconds_and_fractional_seconds が追加されました。テストでは東部標準時 (US/Eastern) 環境下で "1470272280.123456789"%s.%N でパースし、time.nsec が 123456789 になることと、Ruby 標準の Time.strptime と結果が一致することを assert しています。既存のテストスイート 566 件すべてが緑になることが確認され、回帰リスクは無いことが示されました。

設計判断

この修正は 既存コードへの影響を最小限に抑える ことを最優先にした設計判断の表れです。parts_to_time:seconds ブランチに 1 行の加算ロジックを追加しただけで、他の分岐や呼び出し側のインターフェースは変更していません。また、parts.fetch(:sec_fraction, 0) を用いることで sec_fraction が無い場合でも既存の挙動と同等になります。従って、アップグレード時にアプリケーション側で特別な対応は不要です。

まとめ

ActiveSupport::TimeZone#strptime がエポック秒に付随するサブ秒を正しく扱えるようになり、Rails が提供する日時パースと Ruby 標準ライブラリの挙動が一致しました。今回の変更はバグ修正に留まりつつ、コードサイズは最小で後方互換性を維持した点が評価できます。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
3221d2ab

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的な変更、設計判断、まとめが揃っており、総論→各論→結論 の構成が明確です。

カスタムMarkdown構文 ⚠ WARNING

シンタックスハイライト・GitHubリンク記法の正確性

PRリンクが `[PR #57635](URL)` 形式となっており、要求された `[#57635](URL)` 形式とは異なりますが、他のMarkdown構文は正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

専門的なエンジニア向けの内容で、不要な初心者向け解説はありません。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論・各論・結論の段落で構成され、トピックセンテンスで始まり1段落1トピック、長さも適切です。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内のコードスニペットは提供されたDiffと完全に一致しており、変更点が正しく反映されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`sec_fraction`、`parts_to_time`、`Time.at` などの用語が正しく使用され、PR内容と合致しています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

技術的な説明はPRの要点と一致し、根拠が明示されています。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

全ての主張がPRのタイトル・説明・Diffで裏付けられており、捏造や推測はありません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

テスト件数 566 件や nsec の数値 123456789 など、数値情報は正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルはPRタイトルの意味を正しく日本語化しており、一致しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PRに記載されていない外部知識(LTS 等)は含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現の歪曲はなく、PRの記述と合致しています。