.NET:Почему TryParseExact терпит неудачу в Hmm и Hmmss?
-
19-09-2019 - |
Вопрос
Я пробую использовать DateTime.TryParseExact
метод, и я столкнулся с делом, которое я просто не понимаю.У меня есть несколько форматов и некоторые темы для анализа, каждый из которых должен идеально соответствовать одному из форматов:
var formats = new[]
{
"%H",
"HH",
"Hmm",
"HHmm",
"Hmmss",
"HHmmss",
};
var subjects = new[]
{
"1",
"12",
"123",
"1234",
"12345",
"123456",
};
Затем я пытаюсь разобрать их все и распечатать результаты:
foreach(var subject in subjects)
{
DateTime result;
DateTime.TryParseExact(subject, formats,
CultureInfo.InvariantCulture,
DateTimeStyles.NoCurrentDateDefault,
out result);
Console.WriteLine("{0,-6} : {1}",
subject,
result.ToString("T", CultureInfo.InvariantCulture));
}
Я получаю следующее:
1 : 01:00:00
12 : 12:00:00
123 : 00:00:00
1234 : 12:34:00
12345 : 00:00:00
123456 : 12:34:56
И к моему вопросу...почему он выходит из строя на 123 и 12345?Разве они не должны были стать 01:23:00 и 01: 23:45?Чего я здесь не понимаю?И как я могу заставить его работать так, как я бы ожидал?
Обновить: Итак, похоже, мы, возможно, выяснили, почему это в некотором роде терпит неудачу.Похоже, что H
фактически захватывает две цифры, а затем оставляет только одну для mm
, который затем потерпел бы неудачу.Но есть ли у кого-нибудь хорошая идея о том, как я могу изменить этот код, чтобы получить результат, который я ищу?
Еще одно обновление: Думаю, теперь я нашел разумное решение.Добавил это в качестве ответа.Приму его через 2 дня, если только кто-нибудь другой не придумает что-нибудь еще лучше.Спасибо за помощь!
Решение
Хорошо, итак, я думаю, что теперь я во всем этом разобрался благодаря большему чтению, экспериментам и другим полезным ответам здесь.То, что происходит, это то, что H, m и s на самом деле захватывает две цифры, когда может, даже если для остальной части формата будет недостаточно цифр.Так, например, с форматом Хммм и цифры 123, H схватил бы 12 и было бы только 3 налево.И мм требуется две цифры, поэтому он терпит неудачу. Тадаа.
Итак, в настоящее время мое решение заключается в том, чтобы вместо этого использовать только следующие три формата:
var formats = new[]
{
"%H",
"Hm",
"Hms",
};
Поскольку остальной код из моего вопроса останется прежним, я получу это в результате:
1 : 01:00:00
12 : 12:00:00
123 : 12:03:00
1234 : 12:34:00
12345 : 12:34:05
123456 : 12:34:56
Что, я думаю, должно быть одновременно разумным и приемлемым :)
Другие советы
0123 012345
Я предполагаю, что он ищет длину 2/4/6, когда находит строку чисел, подобную этой.Предполагается, что 123 - это AM или PM?0123 не является двусмысленным в таком смысле.
Если вы не используете разделители даты или времени в шаблоне пользовательского формата, используйте неизменяемый язык для параметра поставщика и самую широкую форму каждого спецификатора пользовательского формата.Например если вы хотите указать часы в шаблоне укажите более широкую форму "HH" вместо более узкой форму "H"
процитировать:http://msdn.microsoft.com/en-us/library/ms131044.aspx
Как указывали другие, H неоднозначно, потому что оно подразумевает 10-часовой рабочий день, где as HH равно 12
Цитирую из MSDN's Использование Отдельных пользовательских Спецификаторов формата:
Строка пользовательского формата даты и времени состоит из двух или более символов.Например, если строка формата состоит только из спецификатора h, строка формата интерпретируется как стандартный спецификатор формата даты и времени.Однако в данном конкретном случае генерируется исключение, поскольку отсутствует стандартный спецификатор формата даты и времени h.
Чтобы использовать единый пользовательский спецификатор формата даты и времени, укажите пробел до или после спецификатора даты и времени или укажите спецификатор формата в процентах (%) перед единым пользовательским спецификатором даты и времени.Например, строки формата "h" и "%h" интерпретируются как строки пользовательского формата даты и времени, которые отображают час, представленный текущим значением даты и времени.Обратите внимание, что если используется пробел, он отображается в результирующей строке в виде буквенного символа.
Итак, должно ли это было быть % H
в первом элементе в formats
массив?
Надеюсь, это поможет, С наилучшими пожеланиями, Том.
Я могу ошибаться, но я подозреваю, что это может быть связано с двусмысленностью, присущей части "H" вашей строки формата - т. Е., учитывая строку "123", вы могли бы иметь дело с часом "1" (01:00) или часом "12" (12:00);и с тех пор , как TryParseExact
не знает, что правильно, оно возвращает false .
Что касается того, почему метод не дает "наилучшего предположения":боюсь, в этом случае документация не на вашей стороне.Из Документация MSDN по дате и времени.Попробуйте проанализировать (курсив мой):
Когда этот метод возвращается, содержит
DateTime
значение, эквивалентное дате и времени, содержащихся в s, если преобразование прошло успешно, илиDateTime.MinValue
если преобразование завершилось неудачей.Преобразование завершается неудачей, если либо s или формат параметр равенnull
, является пустой строкой или не содержит дату и время, которые соответствуют шаблону, указанному в формат.Этот параметр передается неинициализированный.
"123" и "12345" кажутся неоднозначными по отношению к методу TryParseExact.Например, "12345" может быть либо 12:34:50, либо 01:23:45.Хотя это всего лишь предположение.