当我使用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; }
}
}
}
答案 0 :(得分:1)
不幸的是,没有内置类型,当它包含偏移量(在XSD规范中可选)时,您可以将xs:time
值反序列化。
相反,您需要定义自定义类型并实现适当的接口以进行自定义序列化和反序列化。下面是一个最小的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.TheTime
的类型更改为TimeOffset
,并且您的测试将通过。您还可以删除属性中的DataType="time"
,因为它是通过GetSchema
方法在对象中声明的。