Почему DateTime не может выполнять DateTime.ParseExact?
Во время борьбы с проблемами форматирования DateTime.ParseExact я решил передать ParseExact из put из 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 сможет использовать собственный вывод на основе той же строки формата?
Ответы
Ответ 1
Это наглядно демонстрирует, что DateTime.ParseExact
не является безопасным в обратном направлении с помощью Datetime.ToString
. Я не уверен, что это большой ответ, но проблема определенно связана с 3-значным годом формата yyy
. С 1962 года невозможно представить в 3-х цифрах ToString
вынужден использовать 4 цифры. По-видимому, ParseExact
недостаточно умен, чтобы отменить эту логику и вместо этого ищет ровно 3 цифры. Обходным путем является использование yyyy
вместо yyy
. Я хотел бы представить это как ошибку для веб-сайта Microsoft Connect и посмотреть, что из этого выйдет.
Ответ 2
Я удивлен, увидев это, но документация в msdn говорит:
Вы можете указать один из стандартных спецификаторов формата даты и времени или ограниченную комбинацию специализированного спецификатора формата даты и времени
http://msdn.microsoft.com/en-us/library/2h3syy57.aspx
Обновление
Вы можете использовать обходное решение, упомянутое в предыдущем ответе.
Ответ 3
Я взял ваш код, и изменить "yyy" на "yyyy" достаточно, чтобы вернуть "TRUE" для всех (сначала воспроизведя "FALSE", прежде чем я внес какие-либо изменения).
Документация в MSDN неясна, но подчеркивает необходимость указания полной ширины каждого компонента (например, yyyy, а не yyy) без инвариантной культуры:
http://msdn.microsoft.com/en-us/library/w2sa9yss.aspx
Если формат представляет собой шаблон пользовательского формата, который не включает разделители даты или времени (например, "yyyyMMdd HHmm" ), используйте культуру инварианта для параметра поставщика и самую широкую форму каждого спецификатора специального формата. Например, если вы хотите указать часы в шаблоне формата, укажите более широкую форму "HH" вместо более узкой формы "H".
Ответ 4
Microsoft внедрила строковый формат для округления даты DateTime. Вы используете формат "o" или "O".
Вам нужно будет установить параметр styles в DateTime.ParseExact в DateTimeStyles.RoundtripKind.
Подробнее см. в:
http://msdn.microsoft.com/en-us/library/az4se3k1%28v=vs.110%29.aspx#Roundtrip