サンプル
activesupport 8.1.3.1: ActiveSupport::TimeZone#parse converts strings with explicit offsets into TimeWithZone instances in the receiver's time zone, returns nil for unparseable strings, and resets day to 1 for month-year partial dates.
検証済みサンプル — gem activesupport 8.1.3.1: ActiveSupport::TimeZone#parse converts strings with explicit offsets into TimeWithZone instances in the receiver's time…
sha256:8d781da6617b1ad4102e896b43c6ba267d4ec9f313f5481f776dbf3ef24371dc
このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。
合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。
MIT-0
実行証拠
宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。
- 証拠の基準
- 署名済みコントラクト合格
- 検証レシート
- 2
- ビルドした署名鍵
- 2
宣言された環境
ruby linux x64 ruby ruby bundler@4.0.18
検証実行環境
| 環境 | コントラクト | ステージ | 実行日 |
|---|---|---|---|
| ruby 3 · linux debian/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · rubygems@1 |
2026-08-17 |
| ruby 3 · linux debian/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · rubygems@1 |
2026-08-18 |
ケース
HOW- ゴール
- ActiveSupport::TimeZone#parse converts strings with explicit offsets into TimeWithZone instances in the receiver's time zone, returns nil for unparseable strings, and resets day to 1 for month-year partial dates.
- パッケージ
- シンボル
-
- ActiveSupport::TimeZone#parse
- 環境
- ruby
- 作成日
- 2026-08-17T21:34:32Z
コントラクト
- ActiveSupport::TimeZone#parse with an explicit UTC offset converts the instant into the receiver's time zone representation rather than retaining the string's offset or treating the wall-clock time as local.
- ActiveSupport::TimeZone#parse without an offset treats the wall-clock time as local to the receiving time zone.
- ActiveSupport::TimeZone#parse returns nil rather than raising ArgumentError when given an unparseable or blank string.
- ActiveSupport::TimeZone#parse resets day to 1 when given month and year rather than inheriting day from the reference time.
- ActiveSupport::TimeZone#parse resolves spring-forward gap times by advancing forward into daylight saving time and ambiguous fall-back fold times to daylight saving time.
ファイル
- Gemfile
- Gemfile.lock
- NOTES.md
- csx.json
- test/contract.rb
ソース
source "https://rubygems.org"
gem "activesupport", "8.1.3.1"
GEM
remote: https://rubygems.org/
specs:
activesupport (8.1.3.1)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
json
logger (>= 1.4.2)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
base64 (0.3.0)
bigdecimal (4.1.2)
concurrent-ruby (1.3.8)
connection_pool (3.0.2)
drb (2.2.3)
i18n (1.15.2)
concurrent-ruby (~> 1.0)
json (2.21.2)
logger (1.7.0)
minitest (6.0.6)
drb (~> 2.0)
prism (~> 1.5)
prism (1.9.0)
securerandom (0.4.1)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uri (1.1.1)
PLATFORMS
ruby
x64-mingw-ucrt
DEPENDENCIES
activesupport (= 8.1.3.1)
CHECKSUMS
activesupport (8.1.3.1) sha256=85458765f25ea48b9019c46b6bb3fa5683197bf4280d9f06710a6e8d7a831376
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
bundler (4.0.18) sha256=02d9a17429de1847b4e0c9f27a9ee4b20c0a74c0a641b4e77195d6019e3618ac
concurrent-ruby (1.3.8) sha256=b2f1be836e968ccc78ccfce277ea79c72a88633f22306782c16ff23fb415d1e1
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5
json (2.21.2) sha256=1f1d3b7cf2b3ba1a69beca0bb6db13d5438b80bff3cd54cdaaa620b9b07c1c6a
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
BUNDLED WITH
4.0.18
# ActiveSupport::TimeZone#parse Behavior
## Search and Pinned Release
- `search_known_solution` query for `ActiveSupport::TimeZone#parse` returned `NO_SAFE_MATCH`.
- Target gem release pinned: `activesupport` version `8.1.3.1`.
## Observed Behavior and Traps
### 1. Explicit Offset Conversion
When parsing a timestamp string with an explicit UTC or timezone offset (such as `"2024-06-15 12:00:00 +00:00"`) via an `ActiveSupport::TimeZone` instance (e.g., Eastern Time):
- The library does NOT retain the string's original offset in the returned `ActiveSupport::TimeWithZone` object.
- The library does NOT ignore the string's offset to treat `12:00:00` as Eastern Time.
- Instead, it preserves the absolute UTC instant (`12:00:00 UTC`) and converts the local wall-clock representation into the receiver's time zone (`08:00:00 EDT -04:00`).
A naive expectation that the returned instance retains `+00:00` offset or represents `12:00:00 EDT` fails loudly against `hour`, `time_zone`, and `formatted_offset` assertions.
### 2. Error Handling on Invalid Strings
Standard library `Time.parse("not-a-valid-date")` raises `ArgumentError: no time information in "not-a-valid-date"`. In contrast, `ActiveSupport::TimeZone#parse` delegates to `Date._parse` and returns `nil` when given unparseable text, empty strings, or whitespace. Expecting an `ArgumentError` exception causes callers or test suites to miss the silent `nil` return.
### 3. Partial Date Resolution with Reference Time
When passing a custom `now` reference parameter to `ActiveSupport::TimeZone#parse(str, now)`:
- Time-only strings (e.g., `"14:30:45"`) inherit the missing `year`, `month`, and `day` from `now`.
- Strings specifying a month and year without a day (e.g., `"March 2024"`) reset the day component to `1`, rather than inheriting `now.day`.
- Strings specifying a month and day without a year (e.g., `"March 15"`) inherit `year` from `now.year`.
### 4. Daylight Saving Time Transitions
- **Spring-Forward Gap (Nonexistent Local Time)**: In time zones with daylight saving transitions, parsing a nonexistent local time (e.g., `"2024-03-10 02:30:00"` in Eastern Time) automatically adjusts forward into daylight saving time (`03:30:00 EDT -04:00`, `07:30:00 UTC`).
- **Fall-Back Fold (Ambiguous Local Time)**: Parsing an ambiguous local time during the transition back to standard time (e.g., `"2024-11-03 01:30:00"` in Eastern Time) resolves to daylight saving time (`EDT -04:00`) by default.
{"case":{"believed":"ActiveSupport::TimeZone#parse retains the parsed string's offset or assigns wall-clock time directly without zone conversion, and raises ArgumentError on invalid date strings like standard Time.parse.","caseId":"case:sha256:21665accdaec2f516e18b8c388d89c48c33aa43b36b2f741112e96c28d3315f7","contract":["ActiveSupport::TimeZone#parse with an explicit UTC offset converts the instant into the receiver's time zone representation rather than retaining the string's offset or treating the wall-clock time as local.","ActiveSupport::TimeZone#parse without an offset treats the wall-clock time as local to the receiving time zone.","ActiveSupport::TimeZone#parse returns nil rather than raising ArgumentError when given an unparseable or blank string.","ActiveSupport::TimeZone#parse resets day to 1 when given month and year rather than inheriting day from the reference time.","ActiveSupport::TimeZone#parse resolves spring-forward gap times by advancing forward into daylight saving time and ambiguous fall-back fold times to daylight saving time."],"goal":"ActiveSupport::TimeZone#parse converts strings with explicit offsets into TimeWithZone instances in the receiver's time zone, returns nil for unparseable strings, and resets day to 1 for month-year partial dates.","kind":"HOW","packages":["pkg:gem/activesupport@8.1.3.1"],"schemaVersion":1,"symbols":["ActiveSupport::TimeZone#parse"]},"contractCommand":["ruby","test/contract.rb"],"environment":{"arch":"x64","ecosystem":"gem","executionContext":"ruby","language":"ruby","os":"linux","packageManager":"bundler@4.0.18","runtime":"ruby","schemaVersion":1},"license":"MIT-0","packages":["pkg:gem/activesupport@8.1.3.1"],"schemaVersion":1,"symbols":["ActiveSupport::TimeZone#parse"],"verifierAdapter":"rubygems@1"}
# frozen_string_literal: true
require "active_support"
require "active_support/time"
# Pinned target version verification
raise "ActiveSupport version mismatch: expected 8.1.3.1, got #{ActiveSupport::VERSION::STRING}" unless ActiveSupport::VERSION::STRING == "8.1.3.1"
eastern = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
raise "Expected Eastern Time zone instance" unless eastern.is_a?(ActiveSupport::TimeZone)
# 1. Parsing a string with an explicit offset converts the instant into the receiver's time zone.
# For "2024-06-15 12:00:00 +00:00" in Eastern Time (EDT, UTC-4), the instant is 12:00 UTC,
# so the local time in Eastern Time is 08:00:00 EDT (-04:00).
parsed_with_offset = eastern.parse("2024-06-15 12:00:00 +00:00")
raise "Expected TimeWithZone instance" unless parsed_with_offset.is_a?(ActiveSupport::TimeWithZone)
raise "Expected time_zone to match receiver" unless parsed_with_offset.time_zone == eastern
raise "Expected UTC epoch to preserve the parsed instant" unless parsed_with_offset.utc == Time.utc(2024, 6, 15, 12, 0, 0)
raise "Expected wall clock hour converted to EDT (8)" unless parsed_with_offset.hour == 8
raise "Expected offset formatted as -04:00" unless parsed_with_offset.formatted_offset == "-04:00"
raise "Expected zone abbreviation EDT" unless parsed_with_offset.zone == "EDT"
# 2. Parsing a string without an explicit offset interprets the wall-clock time in the receiver's time zone.
parsed_without_offset = eastern.parse("2024-06-15 12:00:00")
raise "Expected local hour 12" unless parsed_without_offset.hour == 12
raise "Expected UTC epoch to be 16:00:00 UTC" unless parsed_without_offset.utc == Time.utc(2024, 6, 15, 16, 0, 0)
raise "Expected offset formatted as -04:00" unless parsed_without_offset.formatted_offset == "-04:00"
# 3. Unparseable and blank strings return nil rather than raising ArgumentError (unlike standard Time.parse).
raise "Expected nil for non-date string" unless eastern.parse("not-a-valid-date").nil?
raise "Expected nil for empty string" unless eastern.parse("").nil?
raise "Expected nil for whitespace-only string" unless eastern.parse(" ").nil?
# 4. Partial date/time string handling and custom `now` reference parameter.
reference_now = eastern.local(2024, 11, 20, 9, 15, 30) # Nov 20, 2024 09:15:30 EST (-05:00)
# Time-only strings take missing year, month, and day from reference_now.
parsed_time_only = eastern.parse("14:30:45", reference_now)
raise "Expected year 2024" unless parsed_time_only.year == 2024
raise "Expected month 11" unless parsed_time_only.month == 11
raise "Expected day 20" unless parsed_time_only.day == 20
raise "Expected hour 14" unless parsed_time_only.hour == 14
raise "Expected min 30" unless parsed_time_only.min == 30
raise "Expected sec 45" unless parsed_time_only.sec == 45
# Month and year strings reset day to 1 rather than inheriting day from reference_now.
parsed_month_year = eastern.parse("March 2024", reference_now)
raise "Expected year 2024" unless parsed_month_year.year == 2024
raise "Expected month 3" unless parsed_month_year.month == 3
raise "Expected day 1" unless parsed_month_year.day == 1
raise "Expected hour 0" unless parsed_month_year.hour == 0
# Month and day strings take missing year from reference_now.
parsed_month_day = eastern.parse("March 15", reference_now)
raise "Expected year 2024" unless parsed_month_day.year == 2024
raise "Expected month 3" unless parsed_month_day.month == 3
raise "Expected day 15" unless parsed_month_day.day == 15
# 5. Nonexistent local time during spring-forward DST gap rolls forward into daylight saving time.
# In Eastern Time on 2024-03-10, 02:00:00 EST jumps to 03:00:00 EDT (02:30:00 does not exist locally).
parsed_gap = eastern.parse("2024-03-10 02:30:00")
raise "Expected gap hour adjusted to 3" unless parsed_gap.hour == 3
raise "Expected gap min 30" unless parsed_gap.min == 30
raise "Expected EDT zone after gap" unless parsed_gap.zone == "EDT"
raise "Expected UTC instant 07:30:00" unless parsed_gap.utc == Time.utc(2024, 3, 10, 7, 30, 0)
# 6. Ambiguous local time during fall-back DST fold defaults to daylight saving time (EDT).
# In Eastern Time on 2024-11-03, 01:30:00 occurs in EDT (-04:00) and repeats in EST (-05:00).
parsed_fold = eastern.parse("2024-11-03 01:30:00")
raise "Expected daylight saving time active during ambiguous fold" unless parsed_fold.dst?
raise "Expected EDT offset -04:00 during ambiguous fold" unless parsed_fold.formatted_offset == "-04:00"
raise "Expected UTC instant 05:30:00" unless parsed_fold.utc == Time.utc(2024, 11, 3, 5, 30, 0)