CodeSampleX

サンプル

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

コントラクト

  1. 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.
  2. ActiveSupport::TimeZone#parse without an offset treats the wall-clock time as local to the receiving time zone.
  3. ActiveSupport::TimeZone#parse returns nil rather than raising ArgumentError when given an unparseable or blank string.
  4. ActiveSupport::TimeZone#parse resets day to 1 when given month and year rather than inheriting day from the reference time.
  5. 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

ソースアーティファクトをダウンロード (tar.gz)

ソース

Gemfile
source "https://rubygems.org"

gem "activesupport", "8.1.3.1"
Gemfile.lock
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
NOTES.md
# 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.
csx.json
{"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"}
test/contract.rb
# 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)

オリジンシーダー

csx-seed