feat(vm): Time — MRI 3.4/4.0 conformance (constructors, parts, conversions, full strftime) - #339
Merged
Merged
Conversation
2026-08-09 17:56 CEST Re-back the Ruby Time class with Go's time.Time (was go-composites/time, whole-second only) to gain nanosecond sub-second precision and fixed-offset zones — the foundation for MRI-faithful Time. Mechanical: the ~24 non-Time bindings that built instants from a Unix second count now call the new unixTime() helper; .t.ToUnix() → .t.Unix(); tzinfo/timecop wrappers updated. Verification: go build/vet clean; full internal/vm test suite green (136s). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-09 18:40 CEST Complete the Ruby Time core class toward MRI 3.4/4.0 on the new time.Time backing: Constructors: Time.new (parts, 7th-arg zone, 4.0 in: keyword), Time.utc/gm, Time.local/mktime (usec 7th arg), Time.at (Integer/Float/Rational/Time, subsec + :millisecond/:microsecond/:nanosecond unit, in:), Time.now(in:). MRI field range-validation (mon/mday/hour/min/sec out of range) with overflow normalised as MRI does (Feb 30 → Mar 2, hour 24 → next day, sec 60 → next minute). Parts: usec/nsec/subsec (Rational)/yday/utc_offset/gmt_offset/gmtoff/utc?/gmt?/ dst?/isdst/to_r, alongside the existing year…sec/wday/zone. subsec is Integer 0 on a whole second (MRI). Conversions: utc/gmtime/localtime mutate-in-place and return self (MRI); getutc/getlocal(offset) return a new Time; round/floor/ceil(ndigits); to_a; Time − Time now returns Float seconds; + accepts fractional seconds. Formatting: a from-scratch strftime covering the full directive set (%Y %C %y %m %d %e %H %k %I %l %M %S %L %N %j %p %P %A %a %B %b %u %w %s %z %:z %::z %Z %U %W %G %V %n %t %% and the %c %D %F %R %r %T %x %X %h compounds) with the -_0^# flags and width; inspect renders the sub-second fraction (4.0); ctime/asctime. Deferred (need require "time"/date stdlib, out of core scope): iso8601/ xmlschema/httpdate/rfc2822/rfc822, Time.parse/strptime rewrite (kept as-is). Verification: CI-exact whole-package coverage gate shows ONLY the tolerated pre-existing partials (time.go 100%); go test ./internal/vm/ green; gofmt + go vet clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-09 18:45 CEST Time conformance work lifts the measured ruby/spec pass total to 12244 (language + core, SPEC_SHA 87b1631). Lock in the win at N−30 = 12214. Verification: fresh-binary ratchet OK (12244 ≥ floor). 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-09 18:47 CEST
Completes the Ruby
Timecore class toward MRI 3.4/4.0.Timeis re-backed with Go'stime.Time(wasgo-composites/time, whole-second only) to gain nanosecond sub-second precision and fixed-offset zones — the foundation MRI-faithfulTimeneeds. Timecop still drivesTime.nowthrough the VM clock seam (vm.nowInstant).Implemented
Constructors —
Time.new(parts, 7th-arg zone string, the 4.0in:keyword),Time.utc/gm,Time.local/mktime(µs 7th arg),Time.at(Integer/Float/Rational/Time;subsec+:millisecond/:microsecond/:nanosecondunit and the:usec/:nsecaliases;in:),Time.now(in:). MRI field range-validation (mon/mday/hour/min/secout of range) with overflow normalised as MRI does (Feb 30 → Mar 2, hour 24 → next day, sec 60 → next minute).Parts —
usecnsecsubsec(Rational, Integer0on a whole second)ydayutc_offset/gmt_offset/gmtoffutc?/gmt?dst?/isdstto_r, alongside the pre-existingyear…sec/wday/zone/tv_*.Conversions —
utc/gmtime/localtimemutate-in-place and return self (MRI);getutc/getlocal(offset)return a new Time;round/floor/ceil(ndigits);to_a.Time − Timenow returns Float seconds;+/-accept fractional seconds.Formatting — a from-scratch
strftimecovering the full directive set (%Y %C %y %m %d %e %H %k %I %l %M %S %L %N %j %p %P %A %a %B %b %u %w %s %z %:z %::z %Z %U %W %G %V %n %t %%and the%c %D %F %R %r %T %x %X %hcompounds) with the-_0^#flags and width;inspectrenders the sub-second fraction (4.0);ctime/asctime.Every value is asserted against real
ruby 4.0.5on fixed instants (no wall-clock/TZ dependence).Deferred (out of core scope / gate risk)
iso8601/xmlschema/httpdate/rfc2822/rfc822and aTime.parse/Time.strptimerewrite need thetime/datestdlib parser — kept as-is (existinggo-compositeslenient parsers untouched). One rbgo-specific convention preserved to avoid churn: a UTC instant renders+0000(notUTC) into_s/inspect, matching the pre-existing Go tests.Verification
time.gois 100% (incl. every error branch).go test ./...exit 0;gofmt+go vet ./internal/vm/clean.🤖 Generated with Claude Code