C# 当反序列化带有数据类型time的XmlElement注释的属性时,XmlSerializer不考虑本地时区

C# 当反序列化带有数据类型time的XmlElement注释的属性时,XmlSerializer不考虑本地时区,c#,timezone,xmlserializer,C#,Timezone,Xmlserializer,当我使用XmlSerializer.deserialize反序列化时间字符串时,我希望它考虑我的本地时区,以便 00:00:00.0000000+01:00 解析为00:00,因为我位于时区GMT+1 我弄错了吗 下面是我正在运行的测试xml反序列化的代码: using System; using System.IO; using System.Xml.Serialization; using Microsoft.VisualStudio.TestTools.UnitTesting; nam

当我使用
XmlSerializer.deserialize
反序列化时间字符串时,我希望它考虑我的本地时区,以便

00:00:00.0000000+01:00
解析为00:00,因为我位于时区GMT+1

我弄错了吗

下面是我正在运行的测试xml反序列化的代码:

using System;
using System.IO;
using System.Xml.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Testing
{
    [TestClass]
    public class FooTest
    {
        [TestMethod]
        public void Test()
        {
            var serializer = new XmlSerializer(typeof(Foo),
                new XmlRootAttribute("Foo"));

            var xml = "<Foo><TheTime>00:00:00.0000000+01:00</TheTime></Foo>";

            var stream = new MemoryStream();
            var writer = new StreamWriter(stream);
            writer.Write(xml);
            writer.Flush();
            stream.Position = 0;

            var f = (Foo) serializer.Deserialize(stream);

            Assert.AreEqual("00:00", f.TheTime.ToShortTimeString()); // actual: 01:00
        }

        [Serializable]
        public class Foo
        {
            [XmlElement(DataType = "time")]
            public DateTime TheTime { get; set; }
        }
    }
}
使用系统;
使用System.IO;
使用System.Xml.Serialization;
使用Microsoft.VisualStudio.TestTools.UnitTesting;
命名空间测试
{
[测试类]
公务舱
{
[测试方法]
公开无效测试()
{
var serializer=新的XmlSerializer(typeof(Foo),
新的XmlRootAttribute(“Foo”);
var xml=“00:00:00.0000000+01:00”;
var stream=newmemoryStream();
var writer=新的StreamWriter(流);
Write.Write(xml);
writer.Flush();
流位置=0;
var f=(Foo)序列化程序。反序列化(流);
Assert.AreEqual(“00:00”,f.TheTime.toSortTimeString());//实际值:01:00
}
[可序列化]
公开课Foo
{
[xmlement(DataType=“time”)]
公共日期时间时间{get;set;}
}
}
}

不幸的是,当
xs:time
值包含偏移量(在XSD规范中是可选的)时,没有内置类型可以将其反序列化为

相反,您需要定义一个自定义类型,并为自定义序列化和反序列化实现适当的接口。下面是一个最小的
TimeOffset
结构

[XmlSchemaProvider("GetSchema")]
public struct TimeOffset : IXmlSerializable
{
    public DateTime Time { get; set; }
    public TimeSpan Offset { get; set; }

    public static XmlQualifiedName GetSchema(object xs)
    {
        return new XmlQualifiedName("time", "http://www.w3.org/2001/XMLSchema");
    }

    XmlSchema IXmlSerializable.GetSchema()
    {
        // this method isn't actually used, but is required to be implemented
        return null;
    }

    void IXmlSerializable.ReadXml(XmlReader reader)
    {
        var s = reader.NodeType == XmlNodeType.Element
            ? reader.ReadElementContentAsString()
            : reader.ReadContentAsString();

        if (!DateTimeOffset.TryParseExact(s, "HH:mm:ss.FFFFFFFzzz",
            CultureInfo.InvariantCulture, DateTimeStyles.None, out var dto))
        {
            throw new FormatException("Invalid time format.");
        }

        this.Time = dto.DateTime;
        this.Offset = dto.Offset;
    }

    void IXmlSerializable.WriteXml(XmlWriter writer)
    {
        var dto = new DateTimeOffset(this.Time, this.Offset);
        writer.WriteString(dto.ToString("HH:mm:ss.FFFFFFFzzz", CultureInfo.InvariantCulture));
    }

    public string ToShortTimeString()
    {
        return this.Time.ToString("HH:mm", CultureInfo.InvariantCulture);
    }
}
定义此项后,您现在可以将
Foo的类型更改为
TimeOffset
,您的测试将通过。您还可以删除属性中的
DataType=“time”
,因为它是通过
GetSchema
方法在对象本身中声明的