-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Description
When using DataContractSerializer with a type that contains a DateTimeOffset, that implements IXmlSerializable, and uses DataContractSerializer in the implementation of ReadXml/WriteXml, on .net7.0+
The xml looks something like this and is the same across versions.
<Container xmlns="http://schemas.datacontract.org/2004/07/">
<TestObject xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Date xmlns:d2p1="http://schemas.datacontract.org/2004/07/System">
<d2p1:DateTime>2025-04-18T02:57:13.1151301Z</d2p1:DateTime>
<d2p1:OffsetMinutes>-240</d2p1:OffsetMinutes>
</Date>
</TestObject>
</Container>The deserialized DateTimeOffset is shifted from the true value. Something like the UTC time is interpreted as the local time, with the specified offset
Reproduction Steps
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
var testObject = new TestObject { Date = DateTimeOffset.Now };
var container = new Container { TestObject = testObject };
var dcsContainer = new DataContractSerializer(typeof(Container));
using var streamContainer = new MemoryStream();
dcsContainer.WriteObject(streamContainer, container);
streamContainer.Position = 0;
var resultContainer = dcsContainer.ReadObject(streamContainer) as Container;
Console.WriteLine(container.TestObject.Date);
Console.WriteLine(resultContainer.TestObject.Date);
Debug.Assert(container.TestObject.Date == resultContainer.TestObject.Date);
public class Container : IXmlSerializable
{
public TestObject TestObject { get; set; }
public XmlSchema? GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
var serializer = new DataContractSerializer(typeof(TestObject));
reader.ReadStartElement();
TestObject = (TestObject)serializer.ReadObject(reader);
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
var serializer = new DataContractSerializer(typeof(TestObject));
serializer.WriteObject(writer, TestObject);
}
}
[DataContract]
public class TestObject
{
[DataMember]
public DateTimeOffset Date { get; set; }
}Expected behavior
It is expected that two lines are printed, both the same value.
Actual behavior
On net48 and net6.0, they do.
4/17/2025 10:45:00 PM -04:00
4/17/2025 10:45:00 PM -04:00
On net7.0+ the last value is shifted by the UTC offset (but still has a UTC offset, so the real time is different)
4/17/2025 10:45:00 PM -04:00
4/18/2025 2:45:00 AM -04:00
Regression?
Yes, on .net framework and .net 6.0
Known Workarounds
within the IXmlSerializable.ReadXml implementation, use reflection to grab the InnerReader from the passed in XmlSerializableReader reader, and pass this inner reader to DataContractSerializer
Configuration
Windows x64
Other information
found when upgrading a CoreWCF application upgrading from .net 6 to 8