Stavros_S
Stavros_S

Reputation: 2235

Formatting a localized date with out the year when the culture is variable

I need to have my dates display in the either M/dd or dd/M depending on the currently set culture. With in our app we explicitly set the culture based off config. We currently format our dates using the following method:

string dateStringFormat =Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortDatePattern;

someDate.ToString(dateStringFormat)

This produces the desired date string formatted to our set culture (I.E. 10/4/2013 or 4.10.2013). But in the case when I need the date to not include the year how can I do that and still make it variable? If I do something like someDate.ToString("dd/MM", dateStringFormat) wouldn't that always keep it in day/month format regardless of the culture? Hopefully my question is clear enough. Thanks for any possible help.

Upvotes: 4

Views: 2174

Answers (5)

dsdel
dsdel

Reputation: 1062

I came up to this post exactly by the same reason from the questioner. However when testing the solutions I came up with problems through different cultures.

Just wanted to share my final solution which does work with all Neutral cultures in .Net:

    private static string GetPatternWithoutYear(string pattern)
    {
        if (pattern.EndsWith("yyyy"))
            pattern = pattern.Substring(0, pattern.Length - 5);
        else if (pattern.StartsWith("yyyy"))
            pattern = pattern.Substring(5);
        // some even end with yyyy.
        else if (pattern.EndsWith("yyyy."))
            pattern = pattern.Substring(0, pattern.Length - 5);
        else if (pattern.EndsWith("yy"))
            pattern = pattern.Substring(0, pattern.Length - 3);
        // and some seldom with yy.
        else if (pattern.EndsWith("yy."))
            pattern = pattern.Substring(0, pattern.Length - 3);
        // bul
        else if (pattern.EndsWith("yyyy 'г.'"))
            pattern = pattern.Substring(0, pattern.Length - 9);
        // tuk
        else if (pattern.EndsWith(".yy 'ý.'"))
            pattern = pattern.Substring(0, pattern.Length - 8);
        return pattern;
    }

Tested with following (I will not paste the result as it is to long):

        var cultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures);
        foreach (var culture in cultures)
        {
            string pattern = culture.DateTimeFormat.ShortDatePattern;
            pattern = GetPatternWithoutYear(pattern);

            Console.WriteLine($"{culture.ThreeLetterISOLanguageName}: {culture.DateTimeFormat.ShortDatePattern.PadRight(12)} {pattern.PadRight(8)} {DateTime.Now.ToString(pattern)}");
        }

First line of results:

ivl: MM/dd/yyyy   MM/dd    03.05
aar: dd/MM/yyyy   dd/MM    05.03
afr: yyyy-MM-dd   MM-dd    03-05
agq: d/M/yyyy     d/M      5.3
aka: yyyy/MM/dd   MM/dd    03.05
amh: dd/MM/yyyy   dd/MM    05.03
ara: dd/MM/yy     dd/MM    05.03
arn: dd-MM-yyyy   dd-MM    05-03
asm: dd-MM-yyyy   dd-MM    05-03
asa: dd/MM/yyyy   dd/MM    05.03
ast: d/M/yyyy     d/M      5.3
aze: dd.MM.yyyy   dd.MM    05.03
aze: dd.MM.yyyy   dd.MM    05.03
aze: dd.MM.yyyy   dd.MM    05.03
bak: dd.MM.yy     dd.MM    05.03
...

Upvotes: 0

Fruitbat
Fruitbat

Reputation: 774

I was looking for the same thing and went with this (essentially a variation on Chris Pratt's answer).

    var model = new List<string>();
    string pat;
    string[] cultures = { "en-GB", "en-US", "ja-JP", "fr-FR" };
    DateTime date1 = new DateTime(2011, 5, 1);

    foreach (var culture in cultures)
    {
        DateTimeFormatInfo dtfi = CultureInfo.CreateSpecificCulture(culture).DateTimeFormat;
        pat = dtfi.ShortDatePattern.Replace("/yyyy", "").Replace("yyyy/", "");

        model.Add(
            String.Format("{0} Date ({1}): {2}", culture, pat, date1.ToString(pat, dtfi))
            );
    }

More Replace calls can be added as required to cater for additional cultures. This was for an ASP MVC project (hence "model"). You might like to replace model.Add with Console.WriteLine.

Output from this example is:

en-GB Date (dd/MM): 01/05
en-US Date (M/d): 5/1
ja-JP Date (MM/dd): 05/01
fr-FR Date (dd/MM): 01/05

Upvotes: 2

Thomas C. G. de Vilhena
Thomas C. G. de Vilhena

Reputation: 14565

Try using the Month format specifier. For instance, this:

var d = new DateTime(2013, 10, 04);
var str = d.ToString("M");
Console.WriteLine(d);

Will output the following in the en-US culture:

October 04

And the following in the pr-BR culture:

4 de outubro

This is the best you can do since there is probably no defined convention for displaying only the month and day portions of a date both as numbers.

Upvotes: 3

Alexei Levenkov
Alexei Levenkov

Reputation: 100547

I believe what you are looking for is not possible as there is no particular order of day/month defined in culture (and I think there are cases where both orderings are possible in same culture for different formats).

You can indeed take ShortDatePattern and strip year portion from it or use day/month order to construct your own.

It may be much safer to redesign your application to either show full format, or show month names + day, or some other way to explicitly specify if it is day or month. 04/10/13 :)

Upvotes: 2

Chris Pratt
Chris Pratt

Reputation: 239290

Kind of hokey, but why not just use Remove on the resulting string?

var dateString = someDate.ToString(dateStringFormat);
var dateStringWithoutYear = dateString.Remove(dateString.Length - 5);

Upvotes: 0

Related Questions