Skip to content

Refuses a duration component past the safe range - #156

Merged
johnnyt merged 1 commit into
mainfrom
pts-o0gr-duration-component-safe-range
Oct 1, 2026
Merged

johnnyt merged 1 commit into
mainfrom
pts-o0gr-duration-component-safe-range

Conversation

@johnnyt

@johnnyt johnnyt commented Oct 1, 2026

Copy link
Copy Markdown
Member

What changes

A duration text whose component, as read, is past the largest safe integer is refused (ruled by the operator, 2026-10-01):

  • parseDuration answers its failing arm with the existing reason invalid_duration_format. No reason token is added.
  • The duration target of the cast answers undefined, as it does for every text it cannot read. That is the cast exemption already accepted in ADR-0002, the Amendment headed "the out-of-range rule's sites, and the cast exemption", which makes a cast total and says a string-to-duration parse past the bound is covered by it.

Before this, such a text read as a duration whose component was infinite (a count too long for a double) or rounded (a count a double cannot hold exactly), which the tagged encoder could not write. The check is in readDuration (src/cast.ts) and runs on each component after the parse has added it up, so it covers a component written too long, a repeated unit that sums past the bound, and the whole part of a fraction. A count with leading zeros is judged by its value.

The reference reads integers of any size. Run in a detached export of predicator-ex v9.4.2 (Elixir 1.18.3, OTP 27), it answers each of the six refused texts in the tests with a duration. ADR-0002 declares the difference.

Also in this change:

  • durationToMilliseconds answers NaN for a component that is not a number, where a bigint or a symbol component used to throw. Its "never throws" promise in the doc comment and the README now holds for an untyped caller.
  • The parseDuration doc comment now names the one exception to "answers what the reference's own duration parse answers".
  • A test comment on durationToMilliseconds's sum past the safe range now says the plain-number answer was decided under the night rule by the conductor, 2026-10-01.

The record

ADR-0002 gains, at its foot, "Amendment: a duration component past the safe integer range is refused when a text is read (2026-10-01)" at Status: proposed. It is an Amendment rather than a Note because docs/adr/README.md says an amendment changes what a record decides and a note does not, and this change alters an answer. It has its own heading rather than sitting under the preceding Note's "What this note does not decide", because that Note changes no answer. git diff origin/main...HEAD -- docs/adr/ shows no removed line.

Changelog

changelog.d/pts-o0gr.md, under ### Changed. No fragment for the durationToMilliseconds guard: that export has not been released yet.

Tests

  • test/cast.test.ts: "refuses a component past the largest safe integer"; "reads a component at the largest safe integer, and one written with leading zeros".
  • test/parse-duration.test.ts: the describe block "parseDuration past the largest safe integer", which asks both the export and the cast for each refused text, and reads one component at the bound.
  • test/duration-to-milliseconds.test.ts: "answers NaN rather than throwing for a component that is not a number".

Sabotage, each run against the three test files and restored byte-equal:

  • removing the safe-range check turned the cast test and the twelve past-the-bound rows of the parseDuration block (six refusals, six agreements with the cast) red;
  • also refusing a component equal to the largest safe integer turned both at-the-bound tests red;
  • removing the per-component type check turned the NaN test red on its no-throw assertion.

The full gate is green on this head.

Provenance

  • The src/index.ts edit is only the parseDuration doc comment. The conductor's file map left it out at first and later authorized it. A sibling change edits only the export list in that file.
  • The duration-unit guard was chosen as a code fix rather than narrowing the README, so README.md is untouched.

Refs: pts-o0gr

A duration text whose component, as read, is not a safe integer is
no longer a duration here: readDuration answers nothing, so the
duration cast answers undefined and parseDuration answers
invalid_duration_format, where both answered a duration whose
component was infinite or rounded. The reference, whose integers
have no bound, answers such a text with a duration, and the
parseDuration doc comment now names that exception. ADR-0002 gains
an Amendment at proposed declaring the difference (ruled by the
operator, 2026-10-01).

durationToMilliseconds answers NaN for a component that is not a
number, rather than throwing on a bigint or a symbol, and the test
comment on its unbounded sum names who decided it.

Refs: pts-o0gr
@johnnyt
johnnyt merged commit f12d11f into main Oct 1, 2026
1 check passed
@johnnyt
johnnyt deleted the pts-o0gr-duration-component-safe-range branch October 1, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant