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