Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom culture aware date format in .NET

Tags:

c#

.net

datetime

In .NET, most of the standard strings used for formatting a DateTime value are culture-aware, for example the ShortDatePattern ("d") format string switches the order of the year/month/day parts around depending on the current culture:

6/15/2009 1:45:30 PM -> 6/15/2009 (en-US)
6/15/2009 1:45:30 PM -> 15/06/2009 (fr-FR)
6/15/2009 1:45:30 PM -> 15.06.2009 (de-DE)

I need something similar for a date format containing only month and day:

6/15/2009 1:45:30 PM -> 6/15 (en-US)
6/15/2009 1:45:30 PM -> 15/06 (fr-FR)
6/15/2009 1:45:30 PM -> 15.06. (de-DE)

Using e.g. the "MM/dd" custom format string doesn't work; it will incorrectly display "01.11" for Jan 11 in the German culture, when I want it to display "11.01."

How can I build a custom format string that takes the order of the date parts into account?

like image 681
matk Avatar asked Jan 09 '12 10:01

matk


2 Answers

When using a custom format string, you specify the exact parts you need and where in the string they should be. This is exactly what is happening.

The format string you have is culturally aware already, as the date separator place holder (/) is indeed outputting the correct character - a ..

Apart from constructing different custom format strings to suit the different cultures, there isn't much else you can do.

This can be put in a resource file for internationalization or held in a dictionary for example.

like image 175
Oded Avatar answered Sep 28 '22 17:09

Oded


Assuming all cultures passed will have a ShortDatePattern that contains M or MM and d or dd in some order with some sort of separator (I can't think of an exception for the Gregorian calendar, but I could be wrong) then the following will work:

private static string FindMonthDayOnly(System.Globalization.CultureInfo ci)
{
  string shortPattern = ci.DateTimeFormat.ShortDatePattern;
  while(shortPattern[0] != 'd' && shortPattern[0] != 'M')
  {
    shortPattern = shortPattern.Substring(1);
    if(shortPattern.Length == 0)
      return ci.DateTimeFormat.ShortDatePattern;
  }
  while(shortPattern[shortPattern.Length - 1] != 'd' && shortPattern[shortPattern.Length - 1] != 'M')
  {
    shortPattern = shortPattern.Substring(0, shortPattern.Length - 1);
    if(shortPattern.Length == 0)
      return ci.DateTimeFormat.ShortDatePattern;
  }
  return shortPattern;
}

If the assumption is very far mis-matched, then it'll revert to ShortDatePattern, though it could also end up showing just the date or just the month.

It fails in not correctly including separators at the end or other indicators when appropriate. For example, it turns the standard format (yyyy-MM-dd) into MM-dd rather than --MM-dd, which is the standard format for month-day combinations with no year.

like image 32
Jon Hanna Avatar answered Sep 28 '22 18:09

Jon Hanna