Почему TimeSpan.ToString() требует выделения разделителей?

Вы можете указать пользовательский формат для объекта DateTime следующим образом:

DateTime.Now.ToString("HH:mm:ss");   // 19:55:23

Но когда я пытаюсь использовать тот же формат для объекта TimeSpan, как это:

DateTime.Now.TimeOfDay.ToString("HH:mm:ss");

Я получаю исключение "Input string was not in a correct format.".

Оказывается, решение состоит в том, что вам нужно избежать символов ':', как в "HH\\:mm\\:ss". Обратите внимание, что существует двойная обратная косая черта, потому что если вы укажете только одну, она сломает строку, поэтому вам тоже нужно будет ее избежать.

Вопрос в том, почему разработчики .NET Framework сделали это так? Должна быть причина. Почему мы не можем использовать специальные спецификаторы формата, не избегая их, как мы можем, с объектом DateTime?

Ищем гуру .NET, чтобы пролить свет на эту тему.

Ответ 1

Как указано в документации, одна из отличий между спецификаторами формата DateTime.ToString и TimeSpan.ToString заключается в следующем: пользовательские спецификации формата TimeSpan не включают разделитель разделителей символы, такие как символы, которые отделяют дни от часов, часов от минут или секунд от дробных секунд. Вместо этого эти символы должны быть включены в строку пользовательского формата в виде строковых литералов.

В контраст с TimeSpan (см. таблицу спецификаторов формата в документах), спецификаторы формата DateTime включают в себя предопределенные символы для разделителя даты / и для Сепаратор времени :. Это означает, что, например, для итальянской культуры точка с запятой будет распознана как разделитель времени (а не буквальная) и будет заменена символом .:

    // outputs 09.57.18 instead of 09:57:18 because of Italian culture.
    Console.WriteLine(DateTime.Now.ToString("hh:mm:ss", CultureInfo.GetCultureInfo("it-IT")));

Я думаю, что разработчики .NET сделали такую ​​разницу между DateTime и TimeSpan строковыми формами намеренно, и это разумно. Это потому, что исторически дата/время были отформатированы по-разному для разных культур. И .NET попытался предоставить средства глобализации в этом отношении вместе с типом DateTime. Но TimeSpan не получал таких "глобализационных" обязанностей, это всего лишь тип, представляющий период времени, и его форматирование не привязано к какой-либо специфике культуры (если они когда-либо существовали), но вместо этого форматирование ее постоянно различные настройки культуры.