Преобразование DateTime в Utc только в том случае, если уже не Utc

Я использую структуру DateTimeWithZone, которую Jon Skeet опубликовал в Создание DateTime в определенном часовом поясе в С# fx 3.5

Это не работало точно для моей ситуации, так как предполагает, что DateTime, переданный в конструкторе, является локальным временем и поэтому преобразует его в Utc с использованием указанного TimeZone.

В моем случае мы будем в основном передавать объекты DateTime уже в Utc (так как это то, что мы храним), поэтому нам нужно выполнить только преобразование, если исходный DateTime.Kind не является Utc.

Поэтому я сменил конструктор на:

    public DateTimeWithZone(DateTime dateTime, TimeZoneInfo timeZone, DateTimeKind kind = DateTimeKind.Utc) {
        dateTime = DateTime.SpecifyKind(dateTime, kind);
        utcDateTime = TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZone);
        this.timeZone = timeZone;
    }

Здесь у нас есть необязательный параметр Kind, который по умолчанию имеет значение Utc.

Однако при запуске этого кода и передаче Utc DateTime генерируется следующее исключение:

Преобразование не может быть завершено, потому что в поставляемом DateTime не было правильно задано свойство Kind. Например, когда свойство Kind является DateTimeKind.Local, исходный часовой пояс должен быть TimeZoneInfo.Local.

В соответствии с документами (http://msdn.microsoft.com/en-us/library/bb495915.aspx):

Если свойство Kind для параметра dateTime равно DateTimeKind.Utc, а параметр sourceTimeZone равно TimeZoneInfo.Utc, этот метод возвращает dateTime без выполнения какого-либо преобразования.

Поскольку время ввода и часовой пояс имеют свойство Kind для Utc, я бы не ожидал получить это исключение.

Я неправильно понял?

Ответ 1

Как и в документах MSDN, если вы передаете DateTime с типом, установленным на что-либо помимо DateTimeKind.Utc, и укажите TimeZone, кроме Utc, функция преобразования вызовет исключение. Это должно быть то, что здесь происходит. В вашем коде вы должны проверить, находится ли DateTime уже в Utc и пропустить преобразование, если оно есть.

Кроме того, поскольку dateTime, с которым вы проходите, будет прикреплен к нему DateTime, вам, вероятно, не нужно передавать отдельный параметр Kind.

из docs

Преобразует время в указанное время зона с координированным универсальным временем (UTC).

означает, что он преобразует из часового пояса, поставляемого в Utc

функция выдает исключение аргумента, если:

dateTime.Kind - DateTimeKind.Utc и sourceTimeZone не равен TimeZoneInfo.Utc.

-или -

dateTime.Kind - DateTimeKind.Local и sourceTimeZone не равен TimeZoneInfo.Local.

-или -

sourceTimeZone.IsInvalidDateTime( dateTime) возвращает true.