Technology Blog Posts by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
Viktor_Sperling
Associate
Associate
613

Intro

With a recent change in UI5 version 1.130, we corrected the formatting of decimal places for currencies.

We now differentiate between two cases:

  • Case 1:  If the style: "long"/"short" format option is not set, and no decimals are provided in the  oFormatOptions of the sap.ui.core.format.NumberFormat.getCurrencyInstance API (either via the direct format option decimals or via currency customizing  as specified by the format option customCurrencies), the given value is formatted with the decimals value defined by the CLDR standard.

  • Case 2:  If the style: "long"/"short" format option is set, only the decimals explicitly set in the oFormatOptions of the sap.ui.core.format.NumberFormat.getCurrencyInstance API, are considered  for the determination of the number of decimal places in the output.
    Any other source for the decimals attribute (i.e. your currency customizing or the CLDR) is not considered anymore.

Case 1: Format option style: "long"/"short" isn't set

What's different?

Previously,  applications may have defined currency formats, which relied on the maxFractionDigits format option to specify the number of decimal places. This is incorrect usage, as the maxFractionDigits parameter is meant to define the maximum but not the actual number of decimals.

Example - Prior to the change:

 

- Values to be formatted: ["123.456", "USD"]
- Format options: {maxFractionDigits: 3}
- Formatted result: "123.456 USD"

 

With our change, this behavior has changed. Now the semantics of the maxFractionDigits/minFractionDigits format options is correctly interpreted for currency formats, namely as the maximum and minimum number of permitted decimals.

Example - After the chang:

 

- Values to be formatted: ["123.456", "USD"]
- Format options: {maxFractionDigits: 3}
- Formatted result: "123.46 USD" (rounding is applied)

 

For the en  locale, the formatted result has 2 decimal places:

  • The maxFractionDigits define a maximum of decimal places
  • The CLDR data defines the USD currency in the en locale with 2 decimal places

As  2 < 3,  this is the correct result. The output does not exceed the maximum number of decimal places in this format, and the currency is formatted according to the locale-specific standard.

This change also affects the formatting of currencies with fewer decimal places than expected by their CLDR configurations.

Example - Prior to the change:

 

- Values to be formatted: ["123.4", "USD"]
- Format options: {minFractionDigits: 0}
- Formatted result: "123.4 USD"

 

In the prior behavior, the number of decimal places remained the same if the number given contained more decimal places than defined by the minFractionDigits option.

Example - After the change:

 

- Values to be formatted: ["123.4", "USD"]
- Format options: {minFractionDigits: 0}
- Formatted result: "123.40 USD"

 

With the new change in place, this is not the case anymore as the CLDR defines the number of decimal places for the USD currency in the given locale as 2. Therefore, a zero is padded at the end.

Case 2: Format option style: "long"/"short" is set

During the implementation of Case 1 it was discovered that the configuration of decimal places determined via any source (currency customizing or CLDR) is also applied to short or long formats of numbers (e.g. 1000.00 USD -> 1.00K USD). This is unnecessary for such formats; therefore, we have now disabled the application of any currency customzing if the format option style: "long"/"short" is set.

The only remaining way to apply decimal place formatting to short or long formats of currencies is the decimals format option.

What's different?

Previously, an application may have expected its currency short or long formats to have the number of decimal places as defined by the currency customizing for the currency, in its output format; this may no longer be the case.

Example - Prior to the change:

 

- Values to be formatted: ["123456", "USD"]
- Format options: {style: 'short', maxFractionDigits: 0}
- Formatted result: "123.00K USD"

 

This result is incorrect, as 2 zeros are padded at the end. The CLDR data determines the decimals format option to 2 for USD.  While this is correct for a format without style short or long, formatted numbers with style often contain a metric prefix like “K” so that using the currency’s decimals is wrong.

Example - After the change:

 

- Values to be formatted: ["123456", "USD"]
- Format options: {style: 'short', maxFractionDigits: 0}
- Formatted result: "123K USD"

 

With our new change, no decimal places are displayed in the output format.

A similar behavior can be observed when customCurrencies are provided.

Example - Prior to the change:

 

- Values to be formatted: ["123456", "USD"]
- Format options: {
                      style: 'short', maxFractionDigits: 0, 
                      customCurrencies: {USD: {decimals: 2}}
                  }
- Formatted result: "123.00K USD"

 

Example - After the change:

 

- Values to be formatted: ["123456", "USD"]
- Format options: {
                      style: 'short', maxFractionDigits: 0,
                      customCurrencies: {USD: {decimals: 2}}
                  }
- Formatted result: "123K USD"

 

It can be observed that the currency customizing is ignored if style: "long"/"short" is set.

To avoid any confusion, this rule does apply even if the currency amount is too small to contain a metric prefix (e.g. "K") in its output format.

Example - Prior to the change:

 

- Values to be formatted: ["123", "USD"]
- Format options: {style: 'short', maxFractionDigits: 0}
- Formatted result: "123.00 USD"

 

The given number too small to be formatted into a short format in the US locale.

Example - After the change:

 

- Values to be formatted: ["123", "USD"]
- Format options: {style: 'short', maxFractionDigits: 0}
- Formatted result: "123 USD"

 

With the new change in place, the currency customizing (in this case via the CLDR) is not applied.

What does that mean for tests and applications?

In case 1:

The new behavior of tests and applications depends on the application setup. If the currency formats either use currency customizing where decimals are defined for all currencies or define a decimals format option for their binding, the behavior stays the same.

If, on the other hand, an application relies on the maxFractionDigits option to always determine the number of decimal places on its currency formats, this cannot be assured anymore. Only if  maxFractionDigits < decimals may the maxFractionDigits option still be used to format the output.

Thus, it is up to the application developer to decide, between one of the following alternatives:

  • Alternative 1 (The application should rely on its currency customizing/the CLDR standard for the decimal places of currencies) - Any failing tests have to be adjusted.
  • Alternative 2 (The application should continue to determine the number of decimal places for currencies itself) - The application has to use the decimals format option instead of the maxFractionDigits option for that.

In case 2:

With style set to short or long, the same alternatives exist as before, but with a slightly different semantic, and it is still up to the application developer to decide:

  • Alternative 1 (The application shouldn't have the currency customizing/the CLDR standard affect its short or long formats by adding decimals) - Any failing tests have to be adjusted.
  • Alternative 2 (The application should continue to always display decimal places in its short or long formats) - The application has to use the decimals format option instead of the maxFractionDigits option for that.

For more information regarding the format options available for our NumberFormat.getCurrencyInstance API, see: sap.ui.core.format.NumberFormat.getCurrencyInstance