Consider the following code to parse a date. (Note that I'm in the EN-gb locale):
const DateTimeStyles DATE_TIME_STYLES = DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.AllowWhiteSpaces;
DateTime dt;
// Current culture for this example is "EN-gb".
if (DateTime.TryParse("31/12", CultureInfo.CurrentUICulture, DATE_TIME_STYLES, out dt))
Console.WriteLine("Parsed correctly"); // Do not want!
else
Console.WriteLine("Did not parse correctly.");
I'm deliberately omitting the year. However, TryParse()
will parse this without any errors, and will substitute the current year.
I'd like to be able to force the user to enter ALL the components of the date (using their local format), so I'd like the above parsing to fail - or to be able to detect that the user didn't enter a year.
I don't really want to use DateTime.TryParseExact()
because then I would have to add code to specify all the different valid formats for all the different supported locales, which is non-trivial and likely error-prone. I suspect this may well be my only sane option, though.
Anyone got any ideas? (Someone here at work has already implemented a "solution" which involves not allowing the current year, which is clearly not a good solution...)
You could query for the culture's patterns, filter out those without a year and then use TryParseExact
on the remaining patterns.
var allPatterns = culture.DateTimeFormat.GetAllDateTimePatterns();
var patternsWithYear = allPatterns.Where(s => s.Contains("y")).ToArray();
bool success = TryParseExact(input, patternsWithYear, culture, styles, out dateTime);
Known bug: This doesn't take escaping into account, you'll need to replace the Contains("y")
call with proper parsing to fix this.
Alternatively you could go with just LongDatePattern
and ShortDatePattern
if you're fine with stricter format constraints.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With