Проблема с DateTime.TryParse с датами в формате гггг-дд-мм

84

У меня есть следующая дата в строковом формате «2011-29-01 12:00 am». Теперь я пытаюсь преобразовать это в формат datetime с помощью следующего кода:

DateTime.TryParse(dateTime, out dt); 

Но я всегда получаю dt как {1/1/0001 12:00:00 AM}. Подскажите, пожалуйста, почему? и как мне преобразовать эту строку в настоящее время.

РЕДАКТИРОВАТЬ: Я только что видел, как все упоминали об использовании аргумента формата. Сейчас я упомяну, что я не могу использовать параметр формата, поскольку у меня есть некоторые настройки для выбора пользовательского формата даты, который хочет пользователь, и на основе этого пользователь может автоматически получать дату в текстовом поле в этом формате через jQuery datepicker.

Рокки Сингх
источник
4
Кстати, вы можете определить, не удалось ли преобразовать, проверив возвращаемое значение TryParse. То есть bool success = DateTime.TryParse(...);.
Джим Мишель

Ответы:

188

Это должно работать на основе вашего примера "2011-29-01 12:00 am"

DateTime dt;
DateTime.TryParseExact(dateTime, 
                       "yyyy-dd-MM hh:mm tt", 
                       CultureInfo.InvariantCulture, 
                       DateTimeStyles.None, 
                       out dt);
Разбитое стекло
источник
8
Обыграй меня. Если вы знаете формат своей входной строки, вы практически всегда должны использовать методы TryParseExact / ParseExact.
Euro Micelli
хорошо, поэтому мой формат даты похож на тот, что в примере, но если значение дня или месяца однозначное, то парсер DateTime выдаст ошибку, потому что он искал две цифры, когда есть только одна. Что бы вы предложили в этом сценарии?
Ciaran Gallagher
11
Чтобы ответить на мой собственный вопрос, в этом случае, если вы используете один символ в формате, он работает как для односимвольных, так и для двухсимвольных дат. например, d / m / yyyy работает 13/11/2012
Ciaran Gallagher
@BrokenGlass, это не работает для меня. Не могли бы вы помочь мне с этим?
Мина
2
@CiaranGallagher Просто небольшое замечание, в дате в вашем комментарии должна использоваться большая
буква
14

Вам нужно использовать ParseExactметод . Это принимает строку в качестве второго аргумента, который определяет формат даты и времени, например:

// Parse date and time with custom specifier.
dateString = "2011-29-01 12:00 am";
format = "yyyy-dd-MM h:mm tt";
try
{
   result = DateTime.ParseExact(dateString, format, provider);
   Console.WriteLine("{0} converts to {1}.", dateString, result.ToString());
}
catch (FormatException)
{
   Console.WriteLine("{0} is not in the correct format.", dateString);
}

Если пользователь может указать формат в пользовательском интерфейсе, вам необходимо преобразовать его в строку, которую вы можете передать в этот метод. Вы можете сделать это, либо разрешив пользователю вводить строку формата напрямую - хотя это означает, что преобразование с большей вероятностью завершится ошибкой, поскольку они введут недопустимую строку формата - либо используя поле со списком, которое представляет им возможные варианты, а вы настройте строки формата для этих вариантов.

Если вероятно, что ввод будет неправильным (например, ввод пользователя), лучше использовать, TryParseExactа не использовать исключения для обработки случая ошибки:

// Parse date and time with custom specifier.
dateString = "2011-29-01 12:00 am";
format = "yyyy-dd-MM h:mm tt";
DateTime result;
if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out result))
{
   Console.WriteLine("{0} converts to {1}.", dateString, result.ToString());
}
else
{
   Console.WriteLine("{0} is not in the correct format.", dateString);
}

Лучшей альтернативой может быть не предлагать пользователю выбор форматов даты, а использовать перегрузку, которая принимает массив форматов :

// A list of possible American date formats - swap M and d for European formats
string[] formats= {"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", 
                   "MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss", 
                   "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", 
                   "M/d/yyyy h:mm", "M/d/yyyy h:mm", 
                   "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm",
                   "MM/d/yyyy HH:mm:ss.ffffff" };
string dateString; // The string the date gets read into

try
{
    dateValue = DateTime.ParseExact(dateString, formats, 
                                    new CultureInfo("en-US"), 
                                    DateTimeStyles.None);
    Console.WriteLine("Converted '{0}' to {1}.", dateString, dateValue);
}
catch (FormatException)
{
    Console.WriteLine("Unable to convert '{0}' to a date.", dateString);
}                                               

Если вы прочитали возможные форматы из файла конфигурации или базы данных, вы можете добавить к ним, когда столкнетесь со всеми различными способами, которыми люди хотят вводить даты.

ChrisF
источник
5

Попробуйте использовать безопасный метод TryParseExact

DateTime temp;
string   date = "2011-29-01 12:00 am";

DateTime.TryParseExact(date, "yyyy-dd-MM hh:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out temp);
KateA
источник
4

Из DateTime в msdn:

Тип: System.DateTime% При возврате из этого метода содержит значение DateTime, эквивалентное дате и времени, содержащимся в s, если преобразование выполнено успешно, или MinValue, если преобразование не удалось . Преобразование завершается ошибкой, если параметр s имеет значение NULL, является пустой строкой ("") или не содержит допустимого строкового представления даты и времени. Этот параметр передается неинициализированным.

Вместо этого используйте parseexact со строкой формата "yyyy-dd-MM hh:mm tt".

RedDeckWins
источник
3

Это работает:

DateTime dt = DateTime.ParseExact("2011-29-01 12:00 am", "yyyy-dd-MM hh:mm tt", System.Globalization.CultureInfo.InvariantCulture);
Лукас С.
источник
1
DateTime dt = DateTime.ParseExact("11-22-2012 12:00 am", "MM-dd-yyyy hh:mm tt", System.Globalization.CultureInfo.InvariantCulture);
Хридаешвар
источник
0

Если вы дадите пользователю возможность изменить формат даты / времени, вам нужно будет создать соответствующую строку формата для использования при синтаксическом анализе. Если вы знаете возможные форматы даты (т.е. пользователь должен выбрать их из списка), это намного проще, потому что вы можете создавать эти строки формата во время компиляции.

Если вы позволите пользователю разрабатывать произвольный формат для формата даты / времени, вам придется создавать соответствующие DateTimeстроки формата во время выполнения.

Джим Мишель
источник
Правильно, Джим. Если вы позволите пользователю создавать произвольный формат для формата даты и времени, тогда вам придется создавать соответствующие строки формата DateTime во время выполнения.
Pinal