Kanjie Lu
Kanjie Lu

Reputation: 1047

Datetime Format in WPF

I would like to display the datetime automatically according to the current culture in the environment.

For example If I use DateTime.ToShortDateString() to convert the Datetime of "May 4 2013",it will be 4/5/2013 in en-us and 5/4/2013 in en-gb.

But what I want to display is 04/05/2013 in en-us and 05/04/2013 in en-gb. The zero cannot be hidden.

And please be noted that the software may be run in various cultures, not just in USA and UK. I don't want to set the datetime format for each culture.

Upvotes: 2

Views: 3440

Answers (2)

madd0
madd0

Reputation: 9313

Given that .NET has its own idea of what each culture's formatting should be, there's not much you can do short of deciding to "improve" on the existing formats.

What I'd do is create an IValueConverter in which I'd take the current (or desired) culture's short date format:

CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern

And replace any occurences of a single d with a dd.

If you require months to have double digits and years to be four digit long, I'd replace single M with MM and make sure there's always four y's.

This approach takes advantage of what .NET considers to be the right order for the date-month-year in each culture and uses what .NET considers to be the right separator too.

The converter might look like this:

class ShortDateConverter : IValueConverter
{
  public object Convert(object data, Type type, object parameter, CultureInfo culture)
  {
    string format = PrepareFormat(culture.DateTimeFormat.ShortDatePattern);

    DateTime date = (DateTime)data;

    return date.ToString(format, culture);
  }

  public object ConvertBack(object data, Type type, object parameter, CultureInfo culture)
  {
    return DateTime.ParseExact((string)data, PrepareFormat(culture.DateTimeFormat.ShortDatePattern), culture);
  }

  private string PrepareFormat(string format)
  {
    if (!format.Contains("dd"))
      format = format.Replace("d", "dd");

    if (!format.Contains("MM"))
      format = format.Replace("M", "MM");

    if (!format.Contains("yyyy"))
      format = format.Replace("yy", "yyyy");

    return format;
  }
}

Upvotes: 6

Corey
Corey

Reputation: 16564

The culture-specific formats will define whether or not leading zeros are present. To change that you'll need to parse the date format specified by the culture, look for non-leading-zero specifiers and synthesize a format that includes leading zeros.

For instance:

static string ShortDateFormat(string culture = null)
{
    CultureInfo ci = CultureInfo.CurrentCulture;
    if (!string.IsNullOrEmpty(culture))
        ci = CultureInfo.GetCultureInfo(culture);

    DateTimeFormatInfo fmtinfo = ci.DateTimeFormat;
    if (string.IsNullOrEmpty(fmtinfo.DateSeparator))
        return fmtinfo.ShortDatePattern;

    string fmt = fmtinfo.ShortDatePattern.Replace(fmtinfo.DateSeparator, "!");
    string[] parts = fmt.Split('!');

    for (int i = 0; i < parts.Length; ++i)
    {
        if (parts[i] == "d")
            parts[i] = "dd";
        else if (parts[i] == "M")
            parts[i] = "MM";
    }

    return string.Join(fmtinfo.DateSeparator, parts);
}

Maybe a bit overboard... I don't know if there are any cultures that use a date separator that is more than a single character :)

Pass the result of that as a parameter to DateTime.ToString() to get your output.

Upvotes: 0

Related Questions