@@ -569,34 +569,36 @@ protected CharSequence safeApply(final Object value, final Options options) {
569569 * Usage:
570570 *
571571 * <pre>
572- * {{numberFormat number ["format"] [locale=default]}}
572+ * {{numberFormat number ["format"] [format="format"] [locale="locale"]
573+ * [groupingUsed=true|false] [maximumFractionDigits=...]
574+ * [maximumIntegerDigits=...] [minimumFractionDigits=...]
575+ * [minimumIntegerDigits=...] [parseIntegerOnly=true|false]
576+ * [roundingMode="HALF_UP"]}}
573577 * </pre>
574578 *
575- * Format parameters is one of :
579+ * Format parameters can be :
576580 *
577581 * <ul>
578- * <li>"integer": the integer number format
579- * <li>"percent": the percent number format
580- * <li>"currency": the decimal number format
581- * <li>"pattern": a decimal pattern.
582+ * <li>"integer": formats the number as an integer
583+ * <li>"percent": formats the number as a percentage
584+ * <li>"currency": formats the number as currency
585+ * <li>"pattern": a {@link java.text.DecimalFormat} pattern, e.g. "#,###.00"
582586 * </ul>
583587 *
584- * Otherwise, the default formatter will be used.
588+ * If not specified, the default number format will be used.
589+ * The format option can be specified either as a positional parameter or as a named hash parameter.
585590 *
586- * <p>More options:
591+ * <p>Additional options:
587592 *
588593 * <ul>
589- * <li>groupingUsed: Set whether or not grouping will be used in this format.
590- * <li>maximumFractionDigits: Sets the maximum number of digits allowed in the fraction portion
591- * of a number.
592- * <li>maximumIntegerDigits: Sets the maximum number of digits allowed in the integer portion of
593- * a number
594- * <li>minimumFractionDigits: Sets the minimum number of digits allowed in the fraction portion
595- * of a number
596- * <li>minimumIntegerDigits: Sets the minimum number of digits allowed in the integer portion of
597- * a number.
598- * <li>parseIntegerOnly: Sets whether or not numbers should be parsed as integers only.
599- * <li>roundingMode: Sets the {@link java.math.RoundingMode} used in this NumberFormat.
594+ * <li><strong>locale</strong>: the locale to use, e.g. "en_US" or "fr". Defaults to the system locale.
595+ * <li><strong>groupingUsed</strong>: whether grouping (e.g. thousands separators) should be used.
596+ * <li><strong>maximumFractionDigits</strong>: maximum number of digits in the fractional part.
597+ * <li><strong>maximumIntegerDigits</strong>: maximum number of digits in the integer part.
598+ * <li><strong>minimumFractionDigits</strong>: minimum number of digits in the fractional part.
599+ * <li><strong>minimumIntegerDigits</strong>: minimum number of digits in the integer part.
600+ * <li><strong>parseIntegerOnly</strong>: whether numbers should be parsed as integers only.
601+ * <li><strong>roundingMode</strong>: the {@link java.math.RoundingMode} to apply, e.g. "HALF_UP".
600602 * </ul>
601603 *
602604 * @see NumberFormat
@@ -663,23 +665,31 @@ protected CharSequence safeApply(final Object value, final Options options) {
663665 * @return The number format to use.
664666 */
665667 private NumberFormat build (final Options options ) {
666- if (options .params .length == 0 ) {
667- return NumberStyle .DEFAULT .numberFormat (Locale .getDefault ());
668- }
669- isTrue (
670- options .params [0 ] instanceof String , "found '%s', expected 'string'" , options .params [0 ]);
671- String format = options .param (0 );
672- String localeStr = options .param (1 , Locale .getDefault ().toString ());
673- Locale locale = LocaleUtils .toLocale (localeStr );
668+ final String format = getFormatArgument (options );
669+ final Locale locale = getLocaleArgument (options );
674670 try {
675- NumberStyle style = NumberStyle .valueOf (format . toUpperCase (). trim () );
671+ NumberStyle style = NumberStyle .valueOf (format );
676672 return style .numberFormat (locale );
677- } catch (ArrayIndexOutOfBoundsException ex ) {
678- return NumberStyle .DEFAULT .numberFormat (locale );
679673 } catch (IllegalArgumentException ex ) {
680674 return new DecimalFormat (format , new DecimalFormatSymbols (locale ));
681675 }
682676 }
677+
678+ private String getFormatArgument (final Options options ) {
679+ final String stringifiedFormat = options .param (0 , options .hash ("format" ));
680+ if (stringifiedFormat == null || stringifiedFormat .isBlank ()) {
681+ return NumberStyle .DEFAULT .name ();
682+ }
683+ return stringifiedFormat .toUpperCase ().trim ();
684+ }
685+
686+ private Locale getLocaleArgument (final Options options ) {
687+ final String stringifiedLocale = options .param (1 , options .hash ("locale" ));
688+ if (stringifiedLocale != null && !stringifiedLocale .isBlank ()) {
689+ return LocaleUtils .toLocale (stringifiedLocale );
690+ }
691+ return Locale .getDefault ();
692+ }
683693 },
684694
685695 /**
0 commit comments