How to make decimal.Parse to accept multiple cultures

I need to accept 3 decimal data formats in my application:

  • 123456.78 => 123456.78
  • 123,456.78 => 123456.78
  • 123456.78 => 123456.78

I can not assume that one format will be used in a specific situation. I need to get the decimal value from a string, no matter what format it is in.

Is there any reasonable way to do this?

I tried to use

var culture = CultureInfo.CreateSpecificCulture("en-US");

but this does not work on wp7.

So far I have done this:

public static class Extensions
{

    public static decimal toDecimal(this string s)
    {
        decimal res;

        int comasCount=0;
        int periodsCount=0;

        foreach (var c in s)
        {
            if (c == ',')
                comasCount++;
            else if (c == '.')
                periodsCount++;
        }

        if (periodsCount > 1)
            throw new FormatException();
        else if(periodsCount==0 && comasCount > 1)
            throw new FormatException();

        if(comasCount==1)
        {
            // pl-PL
            //parse here
        }else
        {
            //en-US
            //parse here
        }

        return res;
    }
}
+5
source share
3 answers

Try to use var culture = new CultureInfo("en-US");to create a culture. Transferring this culture to decimal.Parseor decimal.TryParsewill correctly analyze the text for each culture.

, , , . , decimal.TryParse("1000,314", NumberStyles.Number, new CultureInfo("en-US"), out result) 1000314m, 1000.314m. decimal.TryParse("1000,314", NumberStyles.Number, new CultureInfo("fr-FR"), out result) 1000.314m.

+3

- :

public static decimal ParseDecimalNumber( string s , string groupSeparators , string decimalPoints )
{
  NumberFormatInfo nfi   = (NumberFormatInfo) CultureInfo.InvariantCulture.NumberFormat.Clone() ;
  NumberStyles     style = NumberStyles.AllowLeadingWhite
                         | NumberStyles.AllowLeadingSign
                         | NumberStyles.AllowThousands
                         | NumberStyles.AllowDecimalPoint
                         | NumberStyles.AllowTrailingSign
                         | NumberStyles.AllowTrailingWhite
                         ;
  decimal          value ;
  bool             parsed = false ;

  for ( int i = 0 ; !parsed && i < groupSeparators.Length ; ++i )
  {

    nfi.NumberGroupSeparator = groupSeparators.Substring(i,1) ;

    for ( int j = 0 ; !parsed && j < decimalPoints.Length ; ++j )
    {
      if ( groupSeparators[i] == decimalPoints[j] ) continue ; // skip when group and decimal separator are identical

      nfi.NumberDecimalSeparator = decimalPoints.Substring(j,1) ;

      parsed = Decimal.TryParse( s , style , nfi , out value ) ;

    }
  }

  if ( !parsed ) throw new ArgumentOutOfRangeException("s") ;

  return value ;

}

:

string groupSeparators = "., " ;
string decimalPoints   = ".,"  ;
Decimal value = ParseDecimalNumber( someStringContainingANumericLiteral , groupSeparators , decimalPoints ) ;
+1

Three TryParse calls with different NumberStylesand IFormatProviderset to null should do this.

0
source

All Articles