feat(vm): Comparable residuals + strict Time/Date parsers - #344
Merged
Conversation
Horodate: 2026-08-10 08:22 CEST Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Horodate: 2026-08-10 08:41 CEST Adds the strict "require 'time'" / "require 'date'" class-method parsers and locks in the Comparable residuals (clamp / between? / <=>-derived operators), which the prelude already provided, behind an explicit MRI-4.0.5 test. WHAT - internal/vm/strict_parsers.go: Time.iso8601/.xmlschema/.rfc2822/.rfc822/ .httpdate and the Date / DateTime siblings iso8601/xmlschema/rfc3339/rfc2822/ rfc822/httpdate. Each accepts ONLY its wire format (a fixed set of Go reference layouts, tried in order) and raises MRI's exact error otherwise: ArgumentError "invalid xmlschema format: <str>" / "not RFC 2822 compliant date: <str>" / "not RFC 2616 compliant date: <str>" for Time, Date::Error "invalid date" for Date / DateTime. httpdate accepts the three RFC 2616 forms (RFC 1123, obsolete RFC 850, asctime). Date / DateTime rebuild through the go-ruby-date constructors, so the reform, JDN core and formatters stay authoritative; round-trips through the instance formatters hold. - Wired via registerStrictTimeParsers (registerTime) and registerStrictDateParsers (registerDate). - internal/vm/strict_parsers_test.go: happy paths, several malformed -> ArgumentError / Date::Error cases, formatter round-trips, and the Comparable clamp / between? / nil-<=> operator errors — all asserted against ruby 4.0.5. DEFERRED - Date.jisx0301 / DateTime.jisx0301: the Japanese-era table (M/T/S/H/R base years) is unexported in go-ruby-date; a follow-up should expose or mirror it. - A zone-less Time.iso8601 resolves to UTC here (deterministic) where MRI uses the machine local zone — the one inherently non-deterministic case. VERIFICATION - go test ./... green (whole-package coverage gate shows only the 10 pre-existing tolerated partials; every new function is 100% incl error branches). - gofmt + go vet ./internal/vm/ clean. - ruby/spec ratchet: 12382 passing (files loaded 2103); FLOOR 12351 -> 12352. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Horodate: 2026-08-10 08:42 CEST
Adds the strict
require 'time'/require 'date'class-method parsers, and locks in theComparableresiduals (already provided by the prelude) behind an explicit MRI-4.0.5 test.(A) Comparable residuals
clamp(2-arg + Range incl. beginless/endless; exclusive-range and reversed-boundArgumentError, non-RangeTypeError),between?, and the<=>-derived operators< <= > >= ==— including the exactArgumentError "comparison of X with Y failed"when<=>is nil, and==staying lenient. These already lived ininternal/vm/prelude.rb; this PR verifies them againstruby 4.0.5(including that==propagates a raising<=>exactly as MRI does) rather than re-implementing.(B) strict Time / Date / DateTime parsers
internal/vm/strict_parsers.go— each accepts only its wire format (a fixed set of Go reference layouts tried in order) and raises MRI's exact error otherwise:Time.iso8601/.xmlschemaYYYY-MM-DDTHH:MM:SS(.fff)?(Z|±HH:MM)?ArgumentError "invalid xmlschema format: <str>"Time.rfc2822/.rfc822Wdy, DD Mon YYYY HH:MM:SS ±HHMMArgumentError "not RFC 2822 compliant date: <str>"Time.httpdateArgumentError "not RFC 2616 compliant date: <str>"Date/DateTime.iso8601 .xmlschema .rfc3339 .rfc2822 .rfc822 .httpdateDate::Error "invalid date"Date / DateTime rebuild through the
go-ruby-dateconstructors, so the reform, JDN core and formatters stay authoritative; round-trips through the instance formatters (#iso8601/#rfc2822/#httpdate/…) hold.Deferred
Date.jisx0301/DateTime.jisx0301— the Japanese-era table (M/T/S/H/R base years) is unexported ingo-ruby-date; a follow-up should expose or mirror it.Time.iso8601resolves to UTC here (deterministic) where MRI uses the machine local zone — the one inherently non-deterministic case.Verification
go test ./...green; whole-package coverage gate shows only the 10 pre-existing tolerated partials — every new function is 100% incl. error branches.gofmt+go vet ./internal/vm/clean.FLOOR12351 → 12352.🤖 Generated with Claude Code