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?
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))
}
}