Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NumberFormat localization issues

I have a monetary amount that is entered by a user and want to validate it. I have written a JSF validator but am having trouble getting this to work in all circumstances. Here is my scenario:
I have users in different Locales and therefore I need to cope with the various methods of input and want to allow the following

English  
1234  
1,234  
1234.56  
1,234.5  

German & Spanish  
1234  
1.234  
1234,56  
1.234,5

French  
1234  
1 234  
1234,56  
1 234,5  

My problem is with French as options 2 & 4 are seen as invalid using this code as the parsing stops at the space.

public void validate(final FacesContext pContext,
                     final UIComponent pComponent,
                     final Object pValue) {

  boolean isValid = true;
  final Locale locale = (Locale)pComponent.getAttributes().get(USERS_LOCALE);
  final Currency currency = (Currency)pComponent.getAttributes().get(CURRENCY);

  final NumberFormat formatter = NumberFormat.getNumberInstance(locale);
  formatter.setGroupingUsed(true);
  formatter.setMinimumFractionDigits(currency.getDefaultFractionDigits());
  formatter.setMaximumFractionDigits(currency.getDefaultFractionDigits());
  final ParsePosition pos = new ParsePosition(0);
  final String stringValue = (String)pValue;

  if (pos.getIndex() != stringValue.length() || pos.getErrorIndex() != -1) {
    isValid = false;
  }
  ...

I also want to ensure that the following are treated as invalid but they all parse successfully (except for French of course)

1,234,9.56 (Invalid grouping)
1,234.567 (too many decimal places for the currency)

Any help will be much appreciated
Ian

like image 409
bluesky Avatar asked Jan 20 '26 07:01

bluesky


1 Answers

The French thousands' separator is actually a non-breaking space, \u00a0. If your input uses a regular space you can change the input:

input = input.replace(' ', '\u00a0');

Another thing you can do is change the grouping symbol to a regular space:

DecimalFormat decimalFormatter = (DecimalFormat) formatter;
DecimalFormatSymbols symbols = decimalFormatter.getDecimalFormatSymbols();
symbols.setGroupingSeparator(' ');
decimalFormatter.setDecimalFormatSymbols(symbols);

Can't recommend this, though. The new formatter won't accept numbers that use a non-breaking space as the grouping character.

like image 127
Joni Avatar answered Jan 21 '26 22:01

Joni