如何确保XML DateTime属性在冬季日期时序列化为冬季时区?
问题:XmlSerializer序列化DataType=Time的DateTime时时区偏移错误
问题场景
当XML模型的属性配置了DataType="time"的XmlElementAttribute时,XmlSerializer会错误地将DateTime序列化为当前系统的夏季时区偏移(+2),而非目标日期实际对应的冬季时区偏移。测试日期为2024年3月7日(布鲁塞尔时区,此时应使用冬季时区+1)。
代码示例
string xmlString = ""; // 模拟前端到请求的映射 var periodModel = new PeriodModel(); var time = new TimeSpan(19, 0, 0); var date = new DateTime(2024, 03, 07); var dateWithTimezone = DateTime.SpecifyKind(date.Date.Add(time), DateTimeKind.Local); periodModel.EndDate = date; periodModel.EndTime = dateWithTimezone; using(var ms = new MemoryStream()) { var serializer = new XmlSerializer(typeof(PeriodModel)); serializer.Serialize(ms, periodModel); var bytes = ms.ToArray(); xmlString = System.Text.Encoding.UTF8.GetString(bytes); } Assert.NotNull(xmlString); xmlString.Should().BeEquivalentTo("?");
XML模型定义
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] public class PeriodModel { [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, DataType = "date")] public DateTime EndDate { get; set; } [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, DataType = "time")] public DateTime EndTime { get; set; } }
实际与预期结果
实际序列化输出片段:
<EndTime xmlns="">19:00:00.0000000+02:00</EndTime>
预期输出:
19:00:00.0000000+01:00
问题原因
XmlSerializer处理DataType="time"的DateTime属性时,不会根据目标日期判断对应的时区偏移(比如夏令时切换),而是直接使用当前系统运行时的时区偏移,导致日期对应的时区偏移与实际不符。
解决方案
将XML/WCF模型中对应属性的DateTime类型替换为string类型,借助DateTime.ToString()方法自动匹配目标日期对应的时区偏移进行格式化,确保输出符合预期的时区偏移:
修改后的模型代码
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] public class PeriodModel { [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, DataType = "date")] public DateTime EndDate { get; set; } [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, DataType = "time")] public string EndTime { get; set; } }
修改后的赋值逻辑
// 替换原EndTime的赋值代码,使用对应格式输出正确时区偏移的字符串 periodModel.EndTime = dateWithTimezone.ToString("HH:mm:ss.fffffffzzz");
内容的提问来源于stack exchange,提问作者Simulan88
相关产品推荐
相关产品推荐

