Skip to content

incorrect DateTimeOffset with DataContractSerializer and IXmlSerializable #114813

@BradBarnich

Description

@BradBarnich

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

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions