Нодатим неверный 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, и это просто не устанавливает тип. Например, используйте это при загрузке на основе UTCDateTime
из базы данных.Вам может понадобиться позвонить
.ToUniversalTime()
, но будьте осторожны, если вы делаете это только в том случае, если местный часовой пояс устройства соответствует вашей ситуации. Например, сделайте это в настольных или мобильных приложениях, где элемент управления пользовательского интерфейса выбирает дату, но вы подразумевали, что это означает UTC вместо местного времени.Возможно, вам придется изменить способ анализа строк в
DateTime
значения, такие как, передаваяDateTimeStyles.RoundTripKind
кDateTime.Parse
вызов (или любой из его вариантов. Например, сделайте это, если вы читаете данные из текста, CSV и т. д.
Если вы хотите избежать принятия решения, не пишите функции, которые принимают DateTime
в качестве ввода или дать DateTime
в качестве вывода. Вместо этого используйте DateTimeOffset
, или используйте типы Noda-Time, такие как Instant
, LocalDateTime
и т. д. как можно раньше.
Вот что сработало для меня:
Instant instant = Instant.FromDateTimeUtc(DateTime.SpecifyKind(datetime, DateTimeKind.Utc));