Подтвердить что ты не робот

Предотвращение изменения часового пояса при десериализации значения DateTime

У меня есть класс, который я сериализую/десериализую, используя XmlSerializer. Этот класс содержит поле DateTime.

При сериализации поле DateTime представляется строкой, которая включает смещение от GMT, например 2010-05-05T09:13:45-05:00. При десериализации эти времена преобразуются в локальное время машины, выполняющей десериализацию.

По причинам, которые не стоит объяснять, я хотел бы предотвратить изменение этого часового пояса. Сериализация происходит в дикой природе, где существует несколько версий этого класса. Десериализация происходит на сервере, который находится под моим контролем. По существу, похоже, что это было бы лучше всего обработать во время десериализации.

Как я могу это сделать, кроме внедрения IXmlSerializable и выполнения всей десериализации "вручную?"

4b9b3361

Ответ 1

Вместо синтаксического анализа как DateTime вы можете проанализировать его как DateTimeOffset и использовать свойство DateTimeOffset.DateTime, чтобы игнорировать часовой пояс, Вот так:

[XmlIgnore()]
public DateTime Time { get; set; }

[XmlElement(ElementName = "Time")]
public string XmlTime
{
    get { return XmlConvert.ToString(Time, XmlDateTimeSerializationMode.RoundtripKind); }
    set { Time = DateTimeOffset.Parse(value).DateTime; }
}

Ответ 2

Что я сделал, это было использовать метод DateTime.SpecifyKind, как показано ниже:

DateTime dateTime = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified);

И это решит мою проблему, я надеюсь, что это поможет вам.

Ответ 3

Не могли бы вы попробовать что-то вроде this post предложить и создать новое свойство строки и XmlIgnore существующий:

Поместите [XmlIgnore] в свойство Time.

Затем добавьте новое свойство:

[XmlElement(DataType="string",ElementName="Time")]
public String TimeString
{
   get { return this.timeField.ToString("yyyy-MM-dd"); }
   set { this.timeField = DateTime.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture); }
}

Ответ 4

Я знаю, что это старо, но надеюсь, что это поможет кому-то в будущем.

Вот XML, который я десериализую:

<timePeriod>1982-03-31T00:00:00+11:00</t

После десериализации XML я получаю 30-е, а не 31-е:

enter image description here

Похоже, что сторонняя сторона, которая производит этот XML (который я использую), меняю TimeZone на +11 во время летнего времени и сохраняю его как +10, если не летнее время (DST).

Согласно Jon Skeet UTC не следует учитывать DST: fooobar.com/info/23891/...


Также обратите внимание на документацию Рекомендации по кодированию с использованием DateTime в .NET Framework:

<суб > Сериализатор XML всегда предполагает, что значения DateTime, которые являются сериализованными, представляют собой локальное машинное время, поэтому он применяет смещение локального часового пояса машины в качестве смещенной части закодированного времени XML. Когда мы десериализуем это на другой машине, исходное смещение вычитается из обрабатываемого значения и добавляется текущее смещение часовой пояс машины. Суб >


Следующий код позволил мне получить дату, отформатированную как 31-й, но она не будет работать на 100% для не Day Dayogogt Сохраняющие даты (данные в этом фиде):
TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
DateTime easternTimeNow = TimeZoneInfo.ConvertTimeFromUtc(dataPoint.timePeriod, easternZone);
System.Diagnostics.Debug.WriteLine(easternTimeNow.ToString());

Следовательно, решение фиксирует XML-канал, поэтому он не изменяет UTC с помощью DST.

РЕДАКТИРОВАТЬ:, почему данные были прикручены

Как оказалось, это НЕ сторонний поставщик, изменяющий UTC с помощью DST. XML-канал создается базой Java Swing, читающей SQL-дБ. Обычно я бы рекомендовал хранить стандартное представление XML (xsd: dateTime) - IS0 8601, но в этом случае использовать строку и копировать все после работы T. Отказ от ответственности, я все еще пытаюсь изменить фид, рекомендую вам НЕ делать это в PROD. Используйте на свой страх и риск!