Проблема кажется воспроизводимой только тогда, когда часовой пояс машины TimeZoneInfo.Local
имеет положительное смещение от UTC, например, (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
.Мне не удалось воспроизвести его в часовых поясах с неположительным смещением, таким как UTC-05:00
или само UTC.
В частности, в JsonReader.ReadDateTimeOffsetString()
вызовустанавливается на DateTimeOffset.TryParse
с использованием DateTimeStyles.RoundtripKind
:
if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
SetToken(JsonToken.Date, dt, false);
return dt;
}
Это, очевидно, приводит к ошибке недостаточного значения в часовых поясах с положительным смещением UTC.Если в отладчике я анализирую с использованием DateTimeStyles.AssumeUniversal
, проблема устраняется.
Возможно, вы захотите сообщить о проблеме об этом в Newtonsoft.Тот факт, что десериализация определенной строки DateTimeOffset
завершается неудачей только в том случае, если часовой пояс компьютера имеет определенные значения, кажется неправильным.
Обходной путь должен использовать IsoDateTimeConverter
чтобы десериализовать ваши DateTimeOffset
свойства с IsoDateTimeConverter.DateTimeStyles
, установленным на DateTimeStyles.AssumeUniversal
.Кроме того, необходимо отключить автоматическое распознавание DateTime
, встроенное в JsonReader
, установив JsonReader.DateParseHandling = DateParseHandling.None
, что необходимо сделать за до , когда считыватель начнет анализировать значение для вашегоDateTimeOffset
properties.
Сначала определите следующее JsonConverter
:
public class FixedIsoDateTimeOffsetConverter : IsoDateTimeConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?);
}
public FixedIsoDateTimeOffsetConverter() : base()
{
this.DateTimeStyles = DateTimeStyles.AssumeUniversal;
}
}
Теперь, если вы можете изменить JsonSerializerSettings
для вашего контроллера, используйте следующие настройки:
var settings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None,
Converters = { new FixedIsoDateTimeOffsetConverter() },
};
Если вы не можете легко изменить JsonSerializerSettings
вашего контроллера, вам нужно получить DateParseHandlingConverter
с этого ответа до Как предотвратить использование свойства одного объектапреобразуется в DateTime, когда это строка , и применяет его, а также FixedIsoDateTimeOffsetConverter
к вашей модели следующим образом:
[JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)]
public class RootObject
{
[JsonProperty("revisedDate", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(FixedIsoDateTimeOffsetConverter))]
public DateTimeOffset? RevisedDate { get; set; }
}
DateParseHandlingConverter
должно применяться скорее к самой моделичем свойство RevisedDate
, поскольку JsonReader
уже распознает 0001-01-01T00:00:00
как DateTime
до того, как будет сделан вызов FixedIsoDateTimeOffsetConverter.ReadJson()
.
Обновление
В комментариях , @ RenéSchindhelm пишет, Я создалпроблема, чтобы Newtonsoft знал .Это Сбой десериализации значения DateTimeOffset в зависимости от часового пояса системы # 1731 .