Reputation: 14306
I need to accept 3 decimal data formats in my app:
I cannot assume that one format will be used in particular situation. What I need is get a decimal value from a string no matter in which format it's given.
Is there a smart way to do this?
I was trying to use
var culture = CultureInfo.CreateSpecificCulture("en-US");
but this doesn't seem to work on wp7.
So far I've 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;
}
}
Upvotes: 6
Views: 2990
Reputation: 74267
You might try something like this:
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 ;
}
Usage is simple:
string groupSeparators = "., " ;
string decimalPoints = ".," ;
Decimal value = ParseDecimalNumber( someStringContainingANumericLiteral , groupSeparators , decimalPoints ) ;
Upvotes: 2
Reputation: 35881
Try using var culture = new CultureInfo("en-US");
to create the culture. Passing that culture to decimal.Parse
or decimal.TryParse
will parse the text appropriately for each culture.
Now, keep in mind that each culture may parse the text without failure but not parse it the way it's represented for the original culture. For example decimal.TryParse("1000,314", NumberStyles.Number, new CultureInfo("en-US"), out result)
will result success and 1000314m, not 1000.314m. Whereas decimal.TryParse("1000,314", NumberStyles.Number, new CultureInfo("fr-FR"), out result)
will result in 1000.314m.
Upvotes: 4
Reputation: 14816
Three calls to TryParse with different NumberStyles
and IFormatProvider
set to null should do it.
Upvotes: 0