2010-07-06 2 views
25

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

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

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

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

+0

Может ли кто-нибудь дать мне ссылку на точный ответ на этот вопрос? (Передача DateTime с .Net сервера на клиент JavaScript) – Siddhant

ответ

22

Вместо синтаксического анализа как 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; } 
} 
+0

Кроме того, поскольку я использую структуру сущности, мне пришлось помещать [NotMapped] поверх [XmlElement ...], но это решение отлично подходит для меня. спасибо –

2

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

Помещенный [XmlIgnore] на свойстве времени.

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

[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); } 
} 
+0

Мне нужно десериализовать старые версии класса, используя обновленную версию. Разве это не нарушит совместимость? Я могу переименовать свойство DateTime и добавить свойство строки, которое имеет то же имя, что и для DateTime. Но это сломает клиентов, ссылающихся на свойство DateTime. – Odrade

+1

О, теперь я вижу, что имя элемента останется неизменным в Xml. Позвольте мне попробовать это. – Odrade

+1

Этот код не будет работать с вашими существующими клиентами, потому что DateTime.ParseExact не будет работать (поскольку время не в этом формате). Если вы проанализируете как DateTimeOffset, он будет работать с вашими существующими клиентами. –

2

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

Вот XML Я десериализации:

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

После десериализации XML Я в конечном итоге с 30 не 31:

enter image description here

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

Согласно Jon тарелочкам UTC не должен считать DST: https://stackoverflow.com/a/5495816/495455


отметить также документацию Coding Best Practices Using DateTime in the .NET Framework:

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


Следующий код позволил мне получить дату отформатированный как 31, но это не будет работать 100% для не даты Daylioght Saving (приведенных в данном сырье):

TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time"); 
DateTime easternTimeNow = TimeZoneInfo.ConvertTimeFromUtc(dataPoint.timePeriod, easternZone); 
System.Diagnostics.Debug.WriteLine(easternTimeNow.ToString()); 

Поэтому решение является исправить XML-канал, чтобы он не чередовал UTC с DST.

EDIT:почему данные облажался

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

27

То, что я сделал, это было использовать DateTime.SpecifyKind метод, следующим образом:

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

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

Смежные вопросы