How to Globalise/Internationalise Dates and Numbers using the Compact Framework

Well I learnt something new, lots of languages use a ',' rather than a '.' as the decimal separator and until last night I hadn't really thought through all the implications of that. For a bit of fun (in a dev geek sort of why) I wrote and published a Smartphone Conversion Application called "Convert It" and it seems to have been popular enough, around 800 downloads in 2 days.

Last night I spotted that a guy on a French Smartphone site was having problems with my app, it would throw a format exception on startup. Initially I thought it was just a date format problem and easy to fix but after setting the locale of my phone to "French(France)" and stepping through my code I discovered that the problem was with how I was storing floating point numbers.

I keep floating point ratios in XML as follows:-

<

Item Name="USD" Value="0.8307" />

I just did a System.Convert.ToDouble() and it worked just fine for me and life was good. What I hadn't realised was that if a user running the application had a different locale set then Convert.ToDouble() would throw an exception if the decimal place holder for the language wasn't the fullstop '.' character.

So I grabbed a copy of "Developing International Software" off my shelf (yes it really was there, ummm, but not well read until last night:-)) and finally figured how to store and retrieve numbers and dates in a culture neutral manner. It was actually really simple once I'd figured out what to do, but figuring out how simple it was took quite a bit of time...

using

System.Globalization;

private static CultureInfo Invc = CultureInfo.InvariantCulture; //InvariantCulture is the neutral culture
private static NumberFormatInfo nfi = (NumberFormatInfo)Invc.GetFormat(typeof(System.Globalization.NumberFormatInfo));
private static DateTimeFormatInfo dfi = (DateTimeFormatInfo)Invc.GetFormat(typeof(System.Globalization.DateTimeFormatInfo));

I changed

Convert.ToDouble(myfloatingPointNumberString)
to
double.Parse(myfloatingPointNumberString, nfi);

for the date string I changed from

System.Convert.ToDateTime(myDateString);
to
DateTime.Parse(myDateString, dfi);

I had to make a change to how I saved data to make that culturally neutral as well - simple enough...

did as follows:

thisCategory.item[index].itemValue.ToString(nfi);

and

thisCategory.dataDate.ToString(dfi));

Lessons learned:

  1. Test your app with different locales (under Regional Settings)
  2. When persisting number, dates etc - think about doing in a culture neutral way, it's actually really simple and may save you some pain

Btw, if you are thinking I could have just changed the thread culture then note you cant do that on the compact framework and anyway I don't think that would have been the right approach:-)

Cheers, dave