[SalesForce] Apex – format number with more than 3 digits after decimal point

According to SF documentation Decimal.format() method "Returns the String value of this Decimal using the locale of the context user.", but it leaves only 3 digits after decimal point. It doesn't even matter if you use setScale() method before calling format(). Example from SF documentation:

// U.S. locale
Decimal myDecimal = 12345.6789;
system.assertEquals('12,345.679', myDecimal.format());

As you can see it leaves only 3 digits after decimal point.

Is there a "standard" way to format number in Apex (not Visualforce) using the locale of the context user and leave all the digits after decimal point? Or it should be custom code/logic to handle this?

Best Answer

I've logged an Idea for this issue to ask Salesforce for solving this.

Please also find the following 'work-a-round' code that I've written for my current project to make this failure work either way.

/**
 * Function to print a number String or Decimal into the local Currency
 * Format() only returns up till an accuracy of 3 digits, causing a potential issue
 */
public static String formatCurrency( Object o, Integer numberOfDecimals ) {
    // Construct separators based on UserLocale (Decimal.format() is locale sensitive)
    Decimal value           = 1000.10;
    String formattedValue   = value.format();
    String thousandChar     = formattedValue.substring(1,2);
    String decimalChar      = formattedValue.substring(5,6);

    // fetch input number
    Decimal decVal = 0;
    if      ( o == null )            decVal = 0;
    else if ( o instanceof Decimal ) decVal = ( Decimal ) o;
    else if ( o instanceof String )  decVal = Decimal.valueOf( String.valueOf( o ) );

    // apply rounding or add additional 0 decimals
    decVal = decVal.setScale( numberOfDecimals, RoundingMode.CEILING );

    // use format() to print the Integer including thousand separators in user locale
    // Note: only prints up to an accuracy of 3 and does not print 'ending zeros'
    String formattedString = decVal.format();

    // fetch full decimals string
    String originalNumber = decVal.ToPlainString(); // prints with System separators 
    String decimalString  = originalNumber.substringAfter('.');

    // fetch the integer string (before decimal separator), containing thousand separators
    String integerString  = formattedString.substringBefore( decimalChar );

    // concatenate those together
    return integerString + decimalChar + decimalString;
}

Hope this can help you and please upvote the Idea :)