Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a culture-safe way to get ToShortDateString() and ToShortTimeString() with leading zeros?

I know that I could use a format string, but I don't want to lose the culture specific representation of the date/time format. E.g.

5/4/2011 | 2:06 PM | ... should be 05/04/2011 | 02:06 PM | ...

But when I change it to a different culture, I want it to be

04.05.2011 | 14:06 | ...

without changing the format string. Is that possible?

like image 549
xsl Avatar asked Jul 11 '11 18:07

xsl


4 Answers

You can use the DateTimeFormatInfo.CurrentInfo ShortDatePattern and ShortTimePattern to do the translation:

// Change the culture to something different
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-AT");
DateTime test_datetime = new DateTime(2008, 10, 2, 3, 22, 12);
string s_date = test_datetime.ToString(DateTimeFormatInfo.CurrentInfo);

// For specifically the short date and time
string s_date1 = 
   test_datetime.ToString(DateTimeFormatInfo.CurrentInfo.ShortDatePattern);
string s_time1 = 
   test_datetime.ToString(DateTimeFormatInfo.CurrentInfo.ShortTimePattern);

// Results
// s_date1 == 02.10.2008
// s_time1 == 03:22
like image 151
SwDevMan81 Avatar answered Oct 20 '22 05:10

SwDevMan81


I see only a single solution - you should obtain the current culture display format, patch it so that it meets your requirement and finally format your DateTime value using the patched format string. Here is some sample code:

string pattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
        DateTime dt = DateTime.Now;
        string[] format = pattern.Split(new string[] { CultureInfo.CurrentCulture.DateTimeFormat.DateSeparator }, StringSplitOptions.None);
        string newPattern = string.Empty;
        for(int i = 0; i < format.Length; i++) {
            newPattern = newPattern + format[i];
            if(format[i].Length == 1)
                newPattern += format[i];
            if(i != format.Length - 1)
                newPattern += CultureInfo.CurrentCulture.DateTimeFormat.DateSeparator;
        }

As promised, here is the improved version:

/// <summary>
/// Extensions for the <see cref="DateTime"/> class.
/// </summary>
public static class DateTimeExtensions
{
    /// <summary>
    /// Provides the same functionality as the ToShortDateString() method, but
    /// with leading zeros.
    /// <example>
    /// ToShortDateString: 5/4/2011 |
    /// ToShortDateStringZero: 05/04/2011
    /// </example>
    /// </summary>
    /// <param name="source">Source date.</param>
    /// <returns>Culture safe short date string with leading zeros.</returns>
    public static string ToShortDateStringZero(this DateTime source)
    {
        return ToShortStringZero(source,
            CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern,
            CultureInfo.CurrentCulture.DateTimeFormat.DateSeparator);
    }

    /// <summary>
    /// Provides the same functionality as the ToShortTimeString() method, but
    /// with leading zeros.
    /// <example>
    /// ToShortTimeString: 2:06 PM |
    /// ToShortTimeStringZero: 02:06 PM
    /// </example>
    /// </summary>
    /// <param name="source">Source date.</param>
    /// <returns>Culture safe short time string with leading zeros.</returns>
    public static string ToShortTimeStringZero(this DateTime source)
    {
        return ToShortStringZero(source,
            CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern,
            CultureInfo.CurrentCulture.DateTimeFormat.TimeSeparator);
    }

    private static string ToShortStringZero(this DateTime source, 
        string pattern,
        string seperator)
    {
        var format = pattern.Split(new[] {seperator}, StringSplitOptions.None);

        var newPattern = string.Empty;

        for (var i = 0; i < format.Length; i++)
        {
            newPattern = newPattern + format[i];
            if (format[i].Length == 1)
                newPattern += format[i];
            if (i != format.Length - 1)
                newPattern += seperator;
        }

        return source.ToString(newPattern, CultureInfo.InvariantCulture);
    }
}
like image 36
platon Avatar answered Oct 20 '22 06:10

platon


Really complicated answers here. In reality it's as simple as

datetime.ToString("d", culture) // Short date
datetime.ToString("t", culture) // Short time

For a full list of all formats with example outputs see https://learn.microsoft.com/en-us/dotnet/api/system.datetime.tostring?view=net-5.0.

like image 5
Matti-Koopa Avatar answered Oct 20 '22 04:10

Matti-Koopa


You could also override the CurrentThread.CurrentCulture class. At the beginning of your program you call this method:

    private void FixCurrentDateFormat()
    {
        var cc = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
        var df = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat;
        df.FullDateTimePattern = PatchPattern(df.FullDateTimePattern);
        df.LongDatePattern = PatchPattern(df.LongDatePattern);
        df.ShortDatePattern = PatchPattern(df.ShortDatePattern);
        //change any other patterns that you could use

        //replace the current culture with the patched culture
        System.Threading.Thread.CurrentThread.CurrentCulture = cc;
    }

    private string PatchPattern(string pattern)
    {
        //modify the pattern to your liking here
        //in this example, I'm replacing "d" with "dd" and "M" with "MM"
        var newPattern = Regex.Replace(pattern, @"\bd\b", "dd");
        newPattern = Regex.Replace(newPattern, @"\bM\b", "MM");
        return newPattern;
    }

With this, anywhere you display a date as a string in your program it will have the new format.

like image 3
Mike Avatar answered Oct 20 '22 06:10

Mike