(Предисловие: этот вопрос не предназначен для того, чтобы быть слишком широким или основанным на мнениях, хотя он обязательно субъективен).
Я обнаружил ошибку в моем программном обеспечении, которая использовала dtValue.ToString( "U", CultureInfo.InvariantCulture )
вместо dtValue.ToString( "u", CultureInfo.InvariantCulture )
.
(Полагаю, это произошло потому, что, хотя "R"
и "r"
, "O"
и "o"
различаются в буквенном регистре, .NET обрабатывает их идентично, тогда как "U"
и "u"
представляют очень разные форматы и поведения).
После исправления этой проблемы я посмотрел документацию для U
формата из любопытства и спросил, почему он существует в первомместо, потому что я не могу придумать сценарий использования для U
.
Для тех, кому интересно: U
делает это:
- Если это значение
DateTimeOffset
, тоFormatException
выбрасывается всегда. - Если это значение
DateTime
, то внутренне оно преобразуется в UTC с использованием DateTime.ToUniversalTime
: - Если
value.Kind == DateTimeKind.Utc
, то преобразование не выполняется. - Если
value.Kind == DateTimeKind.Local
или Unspecified
, то текущий UT системного часового пояса локального компьютераСмещение C применяется для преобразования его в UTC.
- Затем значение форматируется с использованием формата
"F"
(DateTimeFormatInfo.FullDateTimePattern
), который зависит от конкретной культуры. InvariantCulture
использует "dddd, dd MMMM yyyy HH:mm:ss"
. en-US
использует "dddd, MMMM d, yyyy h:mm:ss tt"
. en-GB
использует "dd MMMM yyyy HH:mm:ss"
.
Мои рассуждения:
- Поскольку формат зависит от культуры, его нельзя использовать для связи между машинами.
- Если, конечно, вы не используете
InvariantCulture
, но результирующая выходная строка содержит избыточную информацию (название дня) и трудна для анализа информации (полные названия месяцев на английском языке), в то время как машиночитаемое форматирование неизменно использует вариациюISO 8601 yyyy-MM-dd HH:mm[:ss][zzz]
.
- При преобразовании теряется информация, такая как местное время или местное смещение UTC.
- Часто программы будут обрабатывать разные
DateTime
значения без учета DateTimeKind
(например, программы, использующие значение DateTimeKind.Local
, как если бы оно представляло UTC, особенно если часовой пояс локального компьютера - время UTC или британское время (и, таким образом, вы получаете интересные ошибки во время британского летнего времени). - Так что, если вы собираетесь
switch
или перейти на dtValue.Kind
, чтобы явно указывать на преобразование в UTC, тогда вы можете также использовать F
и избегать неявного UTC U
преобразования. - Я ожидал, что
DateTimeKind.Unspecified
значения, отформатированные с U
, вызовут исключение, потому что смещение значения не указано - это удивительно, чтоt ToUniversalTime()
использует текущее смещение часового пояса локального компьютера (как с Local
) вместо того, чтобы жаловаться на предположение. (Тем не менее, именно поэтому мы должны использовать DateTimeOffset
или NodaTime везде, где это возможно, конечно).
DateTimeOffset
просто не поддерживает его (по-видимому, это было намеренно отучить программистов .NET от его использования?).
Мой вопрос:
"Вы когда-либо преднамеренно использовали спецификатор формата U
или видели, что он использовалв рабочем коде? Почему? Это была хорошая идея в то время и все еще хороший выбор? "