При борьбе с DateTime. ParseExact, форматирующий проблемы, я решил подать ParseExact помещенный от DateTime. ToString (), как это:
DateTime date2 = new DateTime(1962, 1, 27);
string[] expectedFormats = { "G", "g", "f", "F", "D", "d", "M/d/yyy", "MM/dd/yyy", "MM-dd-yyy", "MMM dd, yyy", "MMM dd yyy", "MMMM dd, yyy", "MMMM dd yyy" };
bool parsed = false;
foreach (string fmt in expectedFormats)
{
try
{
DateTime dtDateTime = DateTime.ParseExact(date2.ToString(fmt), fmt, new CultureInfo("en-US"));
parsed = true;
}
catch (Exception)
{
parsed = false;
}
Console.WriteLine("[{0}] {1}", parsed,date2.ToString(fmt));
}
Это - вывод:
[True] 1/27/1962 12:00:00 AM
[True] 1/27/1962 12:00 AM
[True] Saturday, January 27, 1962 12:00 AM
[True] Saturday, January 27, 1962 12:00:00 AM
[True] Saturday, January 27, 1962
[True] 1/27/1962
[False] 1/27/1962
[False] 01/27/1962
[False] 01-27-1962
[False] Jan 27, 1962
[False] Jan 27 1962
[False] January 27, 1962
[False] January 27 1962
Что я должен сделать так, чтобы ParseExact проанализировал пользовательские строки формата? Разве я неправ ожидать, что DateTime сможет поглотить свой собственный вывод на основе той же строки формата?
Это наглядно демонстрирует, что DateTime.ParseExact
не является безопасным для обхода Datetime.ToString
. Я не уверен, что это большой ответ, но проблема определенно связана с 3-значным форматом года yyy
. Поскольку 1962 год не может быть представлен в трехзначном формате ToString
вынужден использовать 4 цифры. Очевидно, ParseExact
недостаточно умен, чтобы отменить эту логику, и вместо этого ищет ровно 3 цифры. Обходным решением является использование yyyy
вместо yyy
. Я бы отправил это как ошибку на сайт Microsoft Connect и посмотрел, что из этого выйдет.
Я удивлен, увидев это, но в документации на msdn сказано:
Вы можете указать один из стандартных описателей формата даты и времени или ограниченную комбинацию настраиваемого формата даты и времени спецификатор
http://msdn.microsoft.com/en-us/library/2h3syy57.aspx
Обновление
Вы можете использовать обходной путь, упомянутый в предыдущем ответе.
Я взял ваш код, и замены "yyy" на "yyy" достаточно, чтобы вернуть "TRUE" для всех них (сначала я воспроизвел "FALSE", прежде чем вносить какие-либо изменения).
Документация в MSDN неясна, но подчеркивает необходимость указания полной ширины каждого компонента (например, yyyy, а не yyy) без использования инвариантной культуры:
http://msdn.microsoft.com/en-us/library/w2sa9yss.aspx
Если формат является шаблоном пользовательского формата, который не включает разделители даты или времени (например, "yyyyMMdd HHmm"), используйте инвариантную культуру для параметра поставщика и самую широкую форму каждого спецификатора пользовательского формата. Например, если вы хотите указать часы в шаблоне формата, укажите более широкую форму "HH" вместо более узкой формы "H".