-1

Situation - The thread culture in my web app has been set to 'es' (Spanish)

Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("es");
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("es");

The string value is "0.1" For the following expression,

var value = "0.1"
provider = CultureInfo.CreateSpecificCulture("en-US")
double.TryParse(value.ToString(), NumberStyles.Any, provider, out number)

number returns 1.0. Which makes me think that it is picking the culture info from the thread. Not the one I provide.

The following unit test passes (as expected).

var numberInEnUS = "0.1";
var spanishCulture = CultureInfo.CreateSpecificCulture("es");
culture = new CultureInfo("en-US", false);
Thread.CurrentThread.CurrentCulture = spanishCulture;
Thread.CurrentThread.CurrentUICulture = spanishCulture;
double number;
double.TryParse(numberInEnUs, NumberStyles.Any, culture, out number);
Assert.AreEqual(0.1, number);

So, the question is why does double.TryParse fail in my application? Theoretically, 0.1 for Spanish is 1 (Separator for spanish is a decimal point '.'). However, number 1000.0 does not get converted to 10000. So, it seems that it fails only for 0.1 Any explanation is highly appreciated!

Zuber
  • 577
  • 1
  • 11
  • 29
  • 1
    The culture of the thread should be irrelevant as long as you're passing a specific culture to `double.TryParse()`. I notice you didn't include the code where you set the provider variable; are you 100% sure you're sending the provider you think you're sending? By the way, it's probably better to use `CultureInfo.InvariantCulture` than "en-US", although it shouldn't make a difference in your case. – Magnus Grindal Bakken Sep 30 '13 at 11:55
  • 1
    Wat is `provider` pointing to? That's the most crucial part and it's missing. – H H Sep 30 '13 at 11:56
  • Actually, the number is in English... I changed the above. – Zuber Oct 01 '13 at 12:29

3 Answers3

1

You say "0.1" is number in spanish. Actually not, It is numberInEnglish or something else

var numberInSpanish = "0.1";//this is number in english culture

It should be

var numberInSpanish = "0,1";//<--Note 0,1

NumberDecimalSeparator for spanish is ,. Parse 0,1 you'll get expected result.

var numberInSpanish = "0,1";
var spanishCulture = CultureInfo.CreateSpecificCulture("es");
var culture = new CultureInfo("en-US", false);
Thread.CurrentThread.CurrentCulture = spanishCulture;
Thread.CurrentThread.CurrentUICulture = spanishCulture;
double number;
double.TryParse(numberInSpanish, NumberStyles.Any, spanishCulture, out number);

Here number is correctly parsed to "0.1"

Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
0

Your problem is in the mixture of decimal and thousand separators, namely:

'.' - thousand separator in "es" culture, when parsing, will be ignored (e.g. 1.000,0 == 1000,0)

',' - decimal deparator in "es" culture, separates integer and fractional parts

You can easily convince yourself:

  var spanishCulture = CultureInfo.CreateSpecificCulture("es");
  Char dS = spanishCulture.NumberFormat.NumberDecimalSeparator; // <- ','
  Char tS = spanishCulture.NumberFormat.NumberGroupSeparator;   // <- '.' 

So, in your case the string "0.1" will be converted into 1.0 double since '.' as being a thousand separator in es culture will be ignored. You can do either:

  1. Use Invariant culture instead of "es" one:

    double.TryParse(numberInNeutral, NumberStyles.Any, CultureInfo.InvariantCulture, out number);

  2. Or use actual Spanish number representation:

    var numberInSpanish = "0,1";

    double.TryParse(numberInSpanish, NumberStyles.Any, culture, out number);

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • I tried with InvariantCulture, but still the value is 1.0. It seems to always pick the thread culture. – Zuber Oct 02 '13 at 06:45
0

I finally was able to identify what was wrong. The issue was not with the TryParse() function but the ToString() function.

The value was actually a Double type, not a string as I mentioned above. (My bad, I thought it was not relevant). I was actually doing a value.ToString(). This is where it uses the thread culture and changes the value. So, if the value was 0.1, the value.ToString() changes it to "0,1". It automatically changes the decimal character based on the Thread culture. The TryParse then uses the en-US culture and convert "0,1" to 1.

To fix it, use Convert.ToString instead and pass in the culture info.

At the end, it was just a silly mistake.

LessonLearnt - Be careful when using ToString() in globalized applications!

Community
  • 1
  • 1
Zuber
  • 577
  • 1
  • 11
  • 29