Andrej Tozon's blog

In the Attic


How well do you know your Culture?

When doing code reviews, I often stumble upon a piece of code with some culture-specific information hard-coded in it. One example of this being month names:

string[] months =

This is all fine if your application is intended for English spoken users and all that, but hey - why try and duplicate something, what's already been done for you? CultureInfo class has all the information you need:

string[] months = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames;

And if you need the name of the months in some other supported language, all you have to do is ask [this one's for Slovenia):

string[] months = CultureInfo.GetCultureInfo("sl-SI").DateTimeFormat.MonthNames;

Then again, if all you need is month names in shortened form, the class can also help:

string[] months = CultureInfo.CurrentCulture.DateTimeFormat.AbbreviatedMonthNames;

If you're after just one specific month name, it will bi provided for you [the following line will get you February - obviously]:

string month = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(2);

And so on... The same pattern applies for day names, etc. If there is anything specific that you would want to know about a certain culture, CultureInfo class will give you all the information you need. Given these possibilities, one can even create a custom culture using the CultureAndRegionInfoBuilder class. There's quite a few examples of where this would come in useful.

One thing to note though: The MonthNames properties described above will return you the string array of 13 items; although majority of cultures have 12 months in a year, a few apparently have 13, so be aware of that when using these properties. If month names list is intended for a data source that can be bound to, you may want to return the actual number of months. The following method will return the actual number of months in a given year:

int mothCount = CultureInfo.CurrentCulture.DateTimeFormat.Calendar.GetMonthsInYear(DateTime.Today.Year);

The other way would be just skipping the empty months. There are again, several ways to do this - today, the weapon of choice is fashionable - Linq [or rather - its extensions], although it's most likely not the fastest way of doing it:

string[] cultureMonths = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames;
string[] months = cultureMonths.TakeWhile<string>(month => month.Length > 0).ToArray<string>();

The TakeWhile method will return only those items, for which lambda expression would return true. Also not that I could as easy replace the ToArray<string>() method at the end with ToList<string>() and return a generic list of strings:

List<string> months = cultureMonths.TakeWhile<string>(month => month.Length > 0).ToList<string>();

... but since this is most likely a read-only list, it doesn't really matter.