Нодатим неверный DateTime.Kind для Instant.FromDateTimeUtc

Я пытаюсь справиться с этой проблемой часовых поясов, которая у нас есть. Мы хотели бы сохранить все даты в UTC, а затем преобразовать дату и время в часовой пояс пользователя.

Мы решили использовать Nodatime для этого, так как это кажется правильным подходом. Однако мы испытываем довольно много проблем с этим

Вот как мы конвертируем дату и время в UTC (примечание: сейчас я жестко запрограммировал usersTimeZone)

    public static DateTime ConvertLocaltoUTC(this DateTime dateTime)
    {
        LocalDateTime localDateTime = LocalDateTime.FromDateTime(dateTime);

        IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
        var usersTimezoneId = "Europe/Copenhagen";
        var usersTimezone = timeZoneProvider[usersTimezoneId];

        var zonedDbDateTime = usersTimezone.AtLeniently(localDateTime);
        var returnThis = zonedDbDateTime.ToDateTimeUtc();
        return zonedDbDateTime.ToDateTimeUtc();
    }

И вот как мы конвертируем это обратно

    public static DateTime ConvertUTCtoLocal(this DateTime dateTime)
    {
        Instant instant = Instant.FromDateTimeUtc(dateTime);

        IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;

        var usersTimezoneId = "Europe/Copenhagen"; //just an example

        var usersTimezone = timeZoneProvider[usersTimezoneId];

        var usersZonedDateTime = instant.InZone(usersTimezone);

        return usersZonedDateTime.ToDateTimeUnspecified();
    }

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

Исключение аргумента: недопустимый DateTime.Kind для Instant.FromDateTimeUtc

в первой строке "ConvertUTCtoLocal()" Примером даты и времени может быть: "18.09.2017, 17:28:46" - да, это было с помощью метода ConvertLocalToUTC.

Я предоставляю неправильный формат, или что я делаю здесь неправильно?

1 ответ

Исключение, которое вы показываете:

Исключение аргумента: недопустимый DateTime.Kind для Instant.FromDateTimeUtc

Выкидывается из этого кода:

Instant instant = Instant.FromDateTimeUtc(dateTime);

Это означает, что dateTime.Kind должно быть DateTimeKind.Utc быть конвертируемым в Instant и по какой-то причине это не так.

Если вы посмотрите на результат вашего ConvertLocaltoUTC метод, вы обнаружите, что он имеет .Kind == DateTimeKind.Utc,

Таким образом, проблема лежит в другом месте вашего кода, где бы вы ни создавали dateTime вы переходите к ConvertUTCtoLocal,

Вы можете найти решение может быть одним из следующих:

  • Вам может понадобиться позвонить DateTime.SpecifyKind чтобы установить тип в UTC, но будьте осторожны, чтобы делать это только тогда, когда ваши значения на самом деле UTC, и это просто не устанавливает тип. Например, используйте это при загрузке на основе UTC DateTime из базы данных.

  • Вам может понадобиться позвонить .ToUniversalTime(), но будьте осторожны, если вы делаете это только в том случае, если местный часовой пояс устройства соответствует вашей ситуации. Например, сделайте это в настольных или мобильных приложениях, где элемент управления пользовательского интерфейса выбирает дату, но вы подразумевали, что это означает UTC вместо местного времени.

  • Возможно, вам придется изменить способ анализа строк в DateTime значения, такие как, передавая DateTimeStyles.RoundTripKind к DateTime.Parse вызов (или любой из его вариантов. Например, сделайте это, если вы читаете данные из текста, CSV и т. д.

Если вы хотите избежать принятия решения, не пишите функции, которые принимают DateTime в качестве ввода или дать DateTime в качестве вывода. Вместо этого используйте DateTimeOffset, или используйте типы Noda-Time, такие как Instant, LocalDateTime и т. д. как можно раньше.

Вот что сработало для меня:

Instant instant = Instant.FromDateTimeUtc(DateTime.SpecifyKind(datetime, DateTimeKind.Utc));
Другие вопросы по тегам