blackdrag commented on code in PR #2688:
URL: https://github.com/apache/groovy/pull/2688#discussion_r3563222600


##########
src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java:
##########
@@ -16503,6 +16505,66 @@ public static BigInteger toBigInteger(Number self) {
         return NumberMath.toBigInteger(self);
     }
 
+    
//--------------------------------------------------------------------------
+    // toCurrencyString
+
+    /**
+     * Formats a Number as a currency String using the default locale.
+     *
+     * @param self a Number
+     * @return the currency-formatted String
+     * @since 6.0.0
+     */
+    public static String toCurrencyString(Number self) {
+        return NumberFormat.getCurrencyInstance().format(self);
+    }
+
+    /**
+     * Formats a Number as a currency String using the given locale.
+     * <pre class="groovyTestCase">
+     * assert 1234.5.toCurrencyString(Locale.US) == '$1,234.50'
+     * </pre>
+     *
+     * @param self   a Number
+     * @param locale the locale defining the currency format
+     * @return the currency-formatted String
+     * @since 6.0.0
+     */
+    public static String toCurrencyString(Number self, Locale locale) {
+        return NumberFormat.getCurrencyInstance(locale).format(self);
+    }
+
+    
//--------------------------------------------------------------------------
+    // toPercentString
+
+    /**
+     * Formats a Number as a percent String using the default locale.
+     * The value is scaled by 100 (e.g. {@code 0.945} becomes {@code 94.5%}).
+     *
+     * @param self a Number
+     * @return the percent-formatted String
+     * @since 6.0.0
+     */
+    public static String toPercentString(Number self) {
+        return NumberFormat.getPercentInstance().format(self);
+    }
+
+    /**
+     * Formats a Number as a percent String using the given locale.
+     * The value is scaled by 100 (e.g. {@code 0.945} becomes {@code 94.5%}).
+     * <pre class="groovyTestCase">
+     * assert 0.5.toPercentString(Locale.US) == '50%'
+     * </pre>
+     *
+     * @param self   a Number
+     * @param locale the locale defining the percent format
+     * @return the percent-formatted String
+     * @since 6.0.0
+     */
+    public static String toPercentString(Number self, Locale locale) {
+        return NumberFormat.getPercentInstance(locale).format(self);
+    }
+

Review Comment:
   I usually work with multilingual Apps, already supporting Germany and 
Switzerland influences number formatting and of course currency symbols - the 
language is not even different for this case. The effect is that I have to 
avoid everything that uses some kind of default Locale. And don't get me 
started on date and time. Thus for my practical work these methods are useless. 
I would rather prefer a fixed format, that is not depending on the default 
locale - for everything that depends on the locale in DGM. Which would make the 
percent version ok, but I would still not offer the currency variant. 



##########
src/test/groovy/org/codehaus/groovy/runtime/StringGroovyMethodsTest.java:
##########
@@ -261,4 +263,38 @@ public void testToMethods() {
         assertEquals(Boolean.FALSE, StringGroovyMethods.toBoolean("n"));
         assertEquals(Boolean.FALSE, StringGroovyMethods.toBoolean("0"));
     }
+
+    @Test
+    public void testToNumberWithLocale() {
+        assertEquals(1234.5, StringGroovyMethods.toNumber("1,234.5", 
Locale.US).doubleValue(), 0.0);
+        assertEquals(1234.5, StringGroovyMethods.toNumber("1.234,5", 
Locale.GERMANY).doubleValue(), 0.0);
+        assertEquals(42.0, StringGroovyMethods.toNumber("  42  ", 
Locale.US).doubleValue(), 0.0); // surrounding whitespace trimmed
+        assertThrows(NumberFormatException.class, () -> 
StringGroovyMethods.toNumber("abc", Locale.US));
+        // strict: the whole input must parse, trailing junk is rejected (not 
silently truncated)
+        assertThrows(NumberFormatException.class, () -> 
StringGroovyMethods.toNumber("12abc", Locale.US));
+        assertThrows(NumberFormatException.class, () -> 
StringGroovyMethods.toNumber("", Locale.US));
+    }
+
+    @Test
+    public void testToCurrencyNumberWithLocale() {
+        Number us = StringGroovyMethods.toCurrencyNumber("$1,234.50", 
Locale.US);
+        assertEquals(new BigDecimal("1234.50"), us);
+        assertTrue(us instanceof BigDecimal, "currency should parse to an 
exact BigDecimal");
+        // round-trip through the formatter to avoid hard-coding 
locale-specific symbols/spacing
+        String formatted = DefaultGroovyMethods.toCurrencyString(new 
BigDecimal("1234.50"), Locale.GERMANY);
+        assertEquals(new BigDecimal("1234.50"), 
StringGroovyMethods.toCurrencyNumber(formatted, Locale.GERMANY));
+        assertThrows(NumberFormatException.class, () -> 
StringGroovyMethods.toCurrencyNumber("nope", Locale.US));
+        // strict: trailing text after the amount is rejected
+        assertThrows(NumberFormatException.class, () -> 
StringGroovyMethods.toCurrencyNumber("$1,234.50 and more", Locale.US));
+    }
+
+    @Test
+    public void testToPercentNumberWithLocale() {
+        assertEquals(0.5, StringGroovyMethods.toPercentNumber("50%", 
Locale.US).doubleValue(), 0.0);
+        // Turkish places the percent sign before the number
+        assertEquals(0.5, StringGroovyMethods.toPercentNumber("%50", new 
Locale("tr", "TR")).doubleValue(), 0.0);
+        assertThrows(NumberFormatException.class, () -> 
StringGroovyMethods.toPercentNumber("x", Locale.US));
+        // strict: trailing text after the percent is rejected
+        assertThrows(NumberFormatException.class, () -> 
StringGroovyMethods.toPercentNumber("50% off", Locale.US));
+    }

Review Comment:
   don't forget testing with default local. (saving Locale.getDefault, setting 
with Locale.setDefault before test and restoring with Locale.setDefault after 
the test). 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to