[ 
https://issues.apache.org/jira/browse/GROOVY-12147?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18095765#comment-18095765
 ] 

ASF GitHub Bot commented on GROOVY-12147:
-----------------------------------------

codecov-commenter commented on PR #2699:
URL: https://github.com/apache/groovy/pull/2699#issuecomment-4953775776

   ## 
[Codecov](https://app.codecov.io/gh/apache/groovy/pull/2699?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 Report
   :x: Patch coverage is `33.33333%` with `2 lines` in your changes missing 
coverage. Please review.
   :white_check_mark: Project coverage is 69.1122%. Comparing base 
([`86c6648`](https://app.codecov.io/gh/apache/groovy/commit/86c6648d1e61436fe513afaa85d8d0c403de3cda?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache))
 to head 
([`c4e866e`](https://app.codecov.io/gh/apache/groovy/commit/c4e866eb32c568a89b2ea44f59a6adf4589d3d19?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
   
   | [Files with missing 
lines](https://app.codecov.io/gh/apache/groovy/pull/2699?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 | Patch % | Lines |
   |---|---|---|
   | 
[...g/codehaus/groovy/runtime/StringGroovyMethods.java](https://app.codecov.io/gh/apache/groovy/pull/2699?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fcodehaus%2Fgroovy%2Fruntime%2FStringGroovyMethods.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9vcmcvY29kZWhhdXMvZ3Jvb3Z5L3J1bnRpbWUvU3RyaW5nR3Jvb3Z5TWV0aG9kcy5qYXZh)
 | 33.3333% | [0 Missing and 2 partials :warning: 
](https://app.codecov.io/gh/apache/groovy/pull/2699?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 |
   
   <details><summary>Additional details and impacted files</summary>
   
   
   
   [![Impacted file tree 
graph](https://app.codecov.io/gh/apache/groovy/pull/2699/graphs/tree.svg?width=650&height=150&src=pr&token=1r45138NfQ&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)](https://app.codecov.io/gh/apache/groovy/pull/2699?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   
   ```diff
   @@                Coverage Diff                 @@
   ##               master      #2699        +/-   ##
   ==================================================
   + Coverage     69.1077%   69.1122%   +0.0045%     
     Complexity      34235      34235                
   ==================================================
     Files            1537       1537                
     Lines          129356     129352         -4     
     Branches        23503      23502         -1     
   ==================================================
   + Hits            89395      89398         +3     
   + Misses          31941      31934         -7     
     Partials         8020       8020                
   ```
   
   | [Files with missing 
lines](https://app.codecov.io/gh/apache/groovy/pull/2699?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 | Coverage Δ | |
   |---|---|---|
   | 
[.../codehaus/groovy/runtime/DefaultGroovyMethods.java](https://app.codecov.io/gh/apache/groovy/pull/2699?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fcodehaus%2Fgroovy%2Fruntime%2FDefaultGroovyMethods.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9vcmcvY29kZWhhdXMvZ3Jvb3Z5L3J1bnRpbWUvRGVmYXVsdEdyb292eU1ldGhvZHMuamF2YQ==)
 | `74.9667% <ø> (ø)` | |
   | 
[...g/codehaus/groovy/runtime/StringGroovyMethods.java](https://app.codecov.io/gh/apache/groovy/pull/2699?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fcodehaus%2Fgroovy%2Fruntime%2FStringGroovyMethods.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9vcmcvY29kZWhhdXMvZ3Jvb3Z5L3J1bnRpbWUvU3RyaW5nR3Jvb3Z5TWV0aG9kcy5qYXZh)
 | `82.4108% <33.3333%> (+0.1587%)` | :arrow_up: |
   
   ... and [6 files with indirect coverage 
changes](https://app.codecov.io/gh/apache/groovy/pull/2699/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   </details>
   <details><summary> :rocket: New features to boost your workflow: </summary>
   
   - :snowflake: [Test 
Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, 
report on failures, and find test suite problems.
   - :package: [JS Bundle 
Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save 
yourself from yourself by tracking and limiting bundle sizes in JS merges.
   </details>




> Add locale-aware number, currency and percent formatting/parsing to the GDK
> ---------------------------------------------------------------------------
>
>                 Key: GROOVY-12147
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12147
>             Project: Groovy
>          Issue Type: Improvement
>          Components: groovy-jdk
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>             Fix For: 6.0.0-beta-1
>
>
> h2. Summary
> EDIT: updated to match what it would be after PR#2699
> Groovy can already format and parse numbers, but only in a locale-invariant 
> way. {{String.format(locale, ...)}} / {{sprintf}} cover locale-aware 
> _grouped/decimal_ output, and {{"1234.50".toBigDecimal()}} covers _canonical_ 
> parsing — but there is no idiomatic way to:
> * format a number as *locale currency* ({{"€1.234,50"}}) or *locale percent* 
> ({{"94,5 %"}}), or
> * parse a *locale-formatted* number, currency or percent string back to a 
> {{Number}}.
> These are exactly the cases {{java.util.Formatter}} ({{%f}}, {{%%}}) 
> structurally cannot express (no currency conversion; {{%%}} is a literal 
> sign, so no ÷100 scaling and wrong symbol placement in locales such as 
> Turkish {{%94,5}} or German {{94,5 %}}). This issue adds a small set of GDK 
> extension methods that wrap {{java.text.NumberFormat}} to close that gap.
> h2. Motivation
> * {{StringGroovyMethods}} conversions ({{toInteger}}, {{toDouble}}, 
> {{toBigDecimal}}, {{isNumber}}, …) are locale-invariant by construction 
> ({{new BigDecimal(str)}} / {{Double.valueOf(str)}}) — they reject grouping 
> separators, foreign decimal marks, currency symbols and percent signs.
> * {{sprintf}}/{{Formatter}} handles grouped/decimal numbers and localized 
> {{%t}} dates, so no new date/time or {{sprintf}} surface is needed.
> * The only genuinely missing capability is currency/percent formatting and 
> locale-aware parsing — a handful of thin {{NumberFormat}} wrappers.
> h2. Proposed API
> *Formatting* — extension methods on {{Number}} (in {{DefaultGroovyMethods}}):
> {code:java}
> public static String toCurrencyString(Number self)
> public static String toCurrencyString(Number self, Locale locale)
> public static String toPercentString(Number self)
> public static String toPercentString(Number self, Locale locale)
> {code}
> *Parsing* — extension methods on {{CharSequence}} (in 
> {{StringGroovyMethods}}, alongside {{toBigDecimal}}):
> {code:java}
> public static Number toNumber(CharSequence self, Locale locale)
> // public static Number toCurrencyNumber(CharSequence self) // EDIT: removed
> public static Number toCurrencyNumber(CharSequence self, Locale locale)
> // public static Number toPercentNumber(CharSequence self) // EDIT: removed
> public static Number toPercentNumber(CharSequence self, Locale locale)
> {code}
> All actually return {{BigDecimal}}.
> h3. Examples
> Formatting and parsing round-trip for a given locale:
> {code:groovy}
> assert 1234.5.toCurrencyString(Locale.US) == '$1,234.50'
> assert '$1,234.50'.toCurrencyNumber(Locale.US) == 1234.50G
> assert 0.5.toPercentString(Locale.US) == '50%'
> assert '50%'.toPercentNumber(Locale.US) == 0.5
> assert '1.234,5'.toNumber(Locale.GERMANY) == 1234.5
> {code}
> Locale-specific symbols and layout are honoured. Note that the JDK separates 
> the
> number from the currency/percent symbol with a *non-breaking space* (U+00A0), 
> so
> locale-formatted strings should not be hand-written with a plain space:
> {code:groovy}
> def de = Locale.GERMANY
> assert 1234.5.toCurrencyString(de) == "1.234,50\u00A0\u20AC"
> assert "1.234,50\u00A0\u20AC".toCurrencyNumber(de) == 1234.50G
> {code}
> h4. Contracts
> * *Parsing requires an explicit Locale.* There is no default-locale overload:
>   input carries the locale of wherever it came from (a file, a request, a
>   database), which is less often the JVM default than is the case for
>   human-facing output. Where the default is a fair assumption, such as a 
> console
>   application reading what the user typed, pass {{Locale.getDefault()}}
>   explicitly.
> * *Parsing is strict and exact.* The entire (trimmed) input must be consumed, 
> so
>   trailing junk is rejected rather than silently truncated, and the result is 
> an
>   exact {{BigDecimal}}:
> {code:groovy}
> import static groovy.test.GroovyAssert.shouldFail
> assert '50%'.toPercentNumber(Locale.US) instanceof BigDecimal
> shouldFail(NumberFormatException) { '$1,234.50 and 
> more'.toCurrencyNumber(Locale.US) }
> {code}
> * Formatting rounds; parsing does not.* {{NumberFormat}}'s percent instance 
> defaults to zero fraction digits, so the number-to-String direction is lossy:
> {code:groovy}
> assert 0.945.toPercentString(Locale.US) == '94%'      // rounded, not '94.5%'
> assert '94.5%'.toPercentNumber(Locale.US) == 0.945    // parsing keeps the 
> digits
> {code}
> For fraction digits, use {{NumberFormat.getPercentInstance(locale)}} with 
> {{setMaximumFractionDigits(int)}} directly. For locale-aware formatting of a 
> plain number, use {{String.format(locale, '%,.3f', n)}} — the GDK 
> deliberately adds no {{toNumberString}}, since {{String.format}} already 
> covers it.
> h2. Tests
> * Round-trip format→parse for representative locales (US, Germany, France, 
> Turkey — Turkey to cover leading {{%}} placement).
> * Percent parse applies ÷100 scaling.
> * Malformed input throws {{NumberFormatException}}.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to