Вопрос

Я пробую использовать 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.Хотя это всего лишь предположение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top