0

I am receiving as a response from a third-party webservice a JSON having prices formatted in a different way depending on locale.

Below some examples of the format of the text sent (depending on the country)

CH : SFr. 41'700.20
FR : 41 700,20 €
UK : £ 41,700.20

Is there a way in Apex to convert a Formatted String to a Decimal depending on the Locale ?

In need the reverse of myDecimal.format() that takes into account the locale of the User.

1

There aren't any salesforce-provided methods of doing this that I know about.

The are, however, some helpful patterns that we might be able to take advantage of:

  • In your examples, the number of decimals after the decimal separator is always 2
  • decimals are separated into groups of 3
  • we're only dealing with Hindu-Arabic numerals

What you're looking to do is to normalize the input. About the easiest way I can think of doing that is by using a regular expression to strip out the portions of the input that change between locale (namely, everything except the numbers themselves).

List<String> inputAmountStrings = new List<String>{'SFr. 41\'700.20', '41 700,20 €', '£ 41,700.20'};
List<String> firstNormalization = new List<String>();
List<String> secondNormalization = new List<String>();

for(String input :inputAmountStrings){
    // The bulk of the normalization can be accomplished by replacing all non-decimal
    //   characters with whitespace.
    // We can't just replace with a blank space, because we still need to (potentially)
    //   determine the tenths and hundredths decimal places.
    // We can also trim the leading and trailing whitespace right away.
    firstNormalization.add(input.replaceAll('[^0-9]', ' ').trim());
}

// output at this point should be {'41 700 20', '41 700 20', '41 700 20'}

// This second normalization step determines if there are any decimal places or not, and
//   gives us the final results that you can convert to a Decimal type
for(String input :firstNormalization){
    String decimals = input.substringAfterLast(' ');
    // In both cases, we know what the decimals are (if there are any), so
    //   the extra spaces have served their purpose (and we should remove them)
    if(decimals.length() == 2){
        secondNormalization.add(input.substringBeforeLast(' ').remove(' ') + '.' + decimals);
    }else{
        secondNormalization.add(input.remove(' '));
    }
}

// output at this point should be {'41700.20', '41700.20', '41700.20'}

That code is untested, but relatively simple. It should also be able to handle the Indian Numbering System as well (your examples end up being the same in both the western/common numbering system and the Indian numbering system, but things above 100,000 for us are represented as 1,00,000 in the Indian numbering system).

1
  • Thanks for you answer and for the suggestion of workaround. I did'nt want to write an algorithm because I was not sure about all the possible formats of currencies in all countries! But I think that I have no options. – Akram G Nov 14 '17 at 16:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.