Skip to content

Parse quantity format suffixes invariantly#1689

Merged
angularsen merged 1 commit into
masterfrom
agl/parse-invariant
Jul 22, 2026
Merged

Parse quantity format suffixes invariantly#1689
angularsen merged 1 commit into
masterfrom
agl/parse-invariant

Conversation

@angularsen

@angularsen angularsen commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Extracted from #1544 because format-string parsing is unrelated to QuantityValue and is a standalone correctness improvement for the existing formatter. Moving it out keeps the feature PR focused and lets this behavior ship independently.

Changes:

  • Parse significant-digit, abbreviation-index, currency, and percent suffixes with invariant culture.
  • Apply the same parsing rules to the span-based and .NET Framework-compatible code paths.

Tests:

  • Add Format_CustomSpecifierSuffix_ParsesUsingInvariantCulture for abbreviation and significant-digit formats.

Extracted from #1544 (#1544) because format-string parsing is unrelated to QuantityValue and is a standalone correctness improvement for the existing formatter. Moving it out keeps the feature PR focused and lets this behavior ship independently.

Changes:
- Parse significant-digit, abbreviation-index, currency, and percent suffixes with invariant culture.
- Apply the same parsing rules to the span-based and .NET Framework-compatible code paths.

Tests:
- Add Format_CustomSpecifierSuffix_ParsesUsingInvariantCulture for abbreviation and significant-digit formats.
- Verify both net10.0 and net48 QuantityFormatterTests (138 tests per target).
@claude

claude Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review

Small, well-scoped bug fix — no generated code, unit definitions, or public API surface touched.

Breaking changes: None. No public signatures changed. The only behavior change is that format-string suffixes (S1, A0, C, P) are now parsed with InvariantCulture instead of implicitly using CurrentCulture. This can only change behavior for callers running under a culture with a non-default PositiveSign/NegativeSign/digit set — and in those cases the old behavior was arguably already broken (a format string like "S+1" would silently fail to parse and fall through to the standard-numeric-format branch, likely throwing FormatException on "S+1" itself). Worth a one-line mention in the release notes since it's technically a behavior change, even though it's a correctness fix.

Style/conventions: Consistent with the surrounding code — mirrors the existing #if NET / #else split and doesn't introduce new abstractions. Good use of NumberStyles.Integer explicitly on the net48 path to match the default behavior of the span-based overload used on NET.

Generated code / new quantities: N/A — no changes to Common/UnitDefinitions/ or GeneratedCode/.

Correctness: Confirmed the fix is complete — grepped the codebase and QuantityFormatter.cs is the only place with this TryParse(format...) pattern, so there's no other culture-sensitive format-suffix parsing left unfixed elsewhere (e.g. UnitParser/QuantityParser).

Test coverage: Format_CustomSpecifierSuffix_ParsesUsingInvariantCulture is a solid regression test — using a cloned invariant culture with PositiveSign = "!" is a clever way to prove the fix without relying on a specific real-world culture (e.g. some cultures use "+"-like Unicode variants). One gap: the C/P (currsimilarency/percent) suffix branches aren't covered by a test, though the risk there is low since they only gate a TryParse call before throwing FormatException either way.

Nit: The PR body says "Verify both net10.0 and net48 QuantityFormatterTests (138 tests per target)" — might be worth double-checking that count is accurate/intentional if it's meant as a checklist item, but this is a documentation-only concern and doesn't affect the code.

Overall: correct, minimal, well-tested fix. LGTM.

@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96%. Comparing base (7e8da49) to head (5e884c8).

Additional details and impacted files
@@          Coverage Diff           @@
##           master   #1689   +/-   ##
======================================
  Coverage      96%     96%           
======================================
  Files         456     456           
  Lines       30107   30107           
======================================
  Hits        29043   29043           
  Misses       1064    1064           
Flag Coverage Δ
net48 96% <100%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@angularsen
angularsen merged commit d761370 into master Jul 22, 2026
7 checks passed
@angularsen
angularsen deleted the agl/parse-invariant branch July 22, 2026 23:21
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