feat(time): dependency-free Moment on epoch milliseconds #42
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
iterative-works/support!42
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/moment-epoch-millis"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Re-bases
Momentfromopaque type Moment = Instantto an opaque epoch-millisecondLong, in a new dependency-free cross-built moduleiw-support-time— exactly the change its scaladoc anticipated ("the time representation might change… or might be different in different contexts").Why:
Instant.parsealone retains scala-java-time's formatter machinery in Scala.js bundles (~158 KB gzip, measured in claude-code-query's cc-chat spike), and no linker option strips it. Consumers of the SDK model also must not inherit ZIO transitively, so the type needed a zero-dependency home.Design
Long; JSDateis milli-precision, so JVM parse truncates to match.Datebuilt-ins on JS).Date.parseleniency never sees a raw string, so both platforms accept and reject identical inputs.Z(uuuu-MM-ddTHH:mm:ss.SSSZ) — JVMInstant.toStringomits zero millis, JS never does; the pin removes the divergence.Instant.parseand a parse/format round-trip.parseIsoreturnsEither[Moment.ParseError, Moment]— a mini ADT (Malformed,InvalidDate,InvalidTime,Unrepresentable) with the offending input and amessage;parseIsoOptionis the throw-it-away convenience. The tapir codec surfaces the real message. Invalid golden vectors pin the specific error, not just rejection.MomentPlatformtrait, so the platform surface consists of companion members. On the JVM,Moment(instant),Moment(ldt),m.toInstantand bothInstantConversions resolve fromMoment's implicit scope with no import at all — the same surface the old companion had. The trait also carries the protected parse/format engine.Moment.nowkeeps its syntax via an extension onMoment.typeliving incore(where ZIO is); readsClock.currentTime(MILLISECONDS)so nojava.timevalue is touched on any platform.JsonCodec[Moment]/Schema[Moment]rebuilt onparseIso/toIsoString— same ISO-string wire format, butjava.timeis no longer reachable from JS bundles through the codecs.Breaking
Moment.nowneeds the extension in scope — the usualimport works.iterative.core.*covers it; a bareimport works.iterative.core.Momentno longer does.parseIsoreturnsEither[Moment.ParseError, Moment]; callers that wantOptionuseparseIsoOption.Moment(instant),m.toInstant,Conversions) exists on the JVM only — unchanged call syntax there, absent on JS by construction.Downstream
claude-code-query already builds against this locally (its
ConversationLogEntry.timestampbecomesMoment); its branch needs this merged and a snapshot in the forge registry before its CI can resolveiw-support-time.🤖 Generated with Claude Code
f2afe79c3d2e3a055e54