Search code examples
c#parsingdatetimeformat-string

Parsing the DateTime format to get Format String


I would like to be able to get the format string from a DateTime string.

e.g.

"2012-12-08 15:00:00" => "yyyy-MM-dd HH:mm:ss"

"2013/30/01 16:00" => "yyyy/dd/MM HH:mm"

Is this possible?


Solution

  • It would be very hard to do this in a completely general way, but one option would be to extract the relevant DateTimeFormatInfo that you're interested in (using CultureInfo.DateTimeFormat), extract the culture-specific patterns from that (LongDatePattern, LongTimePattern etc), combine the patterns appropriately in some cases (e.g. ShortDatePattern space ShortTimePattern) and then try each pattern in turn using DateTime.TryParseExact - remembering to still specify the culture each time in order to handle date separators etc appropriately.

    When DateTime.TryParseExact returns true, you know you've got a pattern which will parse the given text.

    Sample code - including showing an example where you'd expect it to work but it doesn't:

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    
    class Test
    {
        static void Main()        
        {
            var us = new CultureInfo("en-US");
            var uk = new CultureInfo("en-GB");
            string text = "07/06/2013 11:22:11";
    
            // This one fails, as there's no appropriate time format
            Console.WriteLine(GuessPattern(text, us));
            // This one prints dd/MM/yyyy HH:mm:ss
            Console.WriteLine(GuessPattern(text, uk));
        }
    
        static string GuessPattern(string text, CultureInfo culture)
        {
            foreach (var pattern in GetDateTimePatterns(culture))
            {
                DateTime ignored;
                if (DateTime.TryParseExact(text, pattern, culture,
                                           DateTimeStyles.None, out ignored))
                {
                    return pattern;
                }
            }
            return null;
        }
    
        static IList<string> GetDateTimePatterns(CultureInfo culture)
        {
            var info = culture.DateTimeFormat;
            return new string[]
            {
                info.FullDateTimePattern,
                info.LongDatePattern,
                info.LongTimePattern,
                info.ShortDatePattern,
                info.ShortTimePattern,
                info.MonthDayPattern,
                info.ShortDatePattern + " " + info.LongTimePattern,
                info.ShortDatePattern + " " + info.ShortTimePattern,
                info.YearMonthPattern
                // Consider the sortable pattern, ISO-8601 etc
            };        
        }
    } 
    

    You could potentially hard-code some "extra" date and time formats which you expect to work.

    EDIT: To handle ambiguity, you could easily make GuessPattern return an IEnumerable<string> instead of a single string:

    static IEnumerable<string> GuessPatterns(string text, CultureInfo culture)
    {
        DateTime ignored;
        return GetDateTimePatterns(culture)
            .Where(pattern => DateTime.TryParseExact(text, pattern, culture,
                                                 DateTimeStyles.None, out ignored))
        }
    }