C# WinForm转XML传入Sql Server时日期倒退为前一天如何解决
问题根因
你遇到的时区偏移问题本质是XmlSerializer序列化DateTime类型时的默认行为:
- 当
DateTime.Kind为DateTimeKind.Local时(你在英国时区录入的日期默认就是这个类型),序列化会自动带上本地时区偏移量 - SQL Server解析带时区的XML日期时,会自动转换为UTC时间,
2021-08-05T00:00:00+01:00转UTC就是2021-08-04 23:00:00,截断时间部分后就变成了前一天的日期
解决方案
方案1:仅保留日期部分(最适配你的业务场景)
你的业务里日期只有日期部分、时间固定为0,直接给日期属性标记[XmlElement]特性指定数据类型为date即可,序列化后只会输出纯日期格式,不会带时间和时区:
// 给实体类的对应日期属性添加该特性 [XmlElement(DataType = "date")] public DateTime 你的日期属性名 { get; set; }
序列化后输出的格式为<你的日期属性名>2021-08-05</你的日期属性名>,完全不会出现时区相关问题。
方案2:保留完整日期时间但不带时区偏移
如果需要保留时间部分不需要时区,可选择以下两种实现:
方式A:统一调整DateTime的Kind属性
在序列化前把所有DateTime属性的Kind改为DateTimeKind.Unspecified,XmlSerializer就不会添加时区偏移:
// 扩展方法处理对象内的DateTime属性 public static void AdjustDateTimeKind(object obj) { var properties = obj.GetType().GetProperties() .Where(p => p.PropertyType == typeof(DateTime) || p.PropertyType == typeof(DateTime?)); foreach (var prop in properties) { if (prop.GetValue(obj) is DateTime dt) { prop.SetValue(obj, DateTime.SpecifyKind(dt, DateTimeKind.Unspecified)); } } } // 改造你的XML转换方法 public static string ConvertToXmlDoc(object dataModeldata) { AdjustDateTimeKind(dataModeldata); Type modelType = dataModeldata.GetType(); var writer = new XmlSerializer(modelType); StringWriter sw = new StringWriter(); writer.Serialize(sw, dataModeldata); string xmlDoc = sw.ToString(); return xmlDoc; }
注意:如果你的数据对象存在嵌套的子对象,需要把
AdjustDateTimeKind方法改成递归遍历所有子对象的属性,才能覆盖所有DateTime类型字段。
方式B:添加序列化代理属性
如果不想修改原日期属性的逻辑,可以新增一个字符串类型的代理属性用于序列化,原属性标记为忽略序列化:
[XmlIgnore] public DateTime 你的日期属性名 { get; set; } [XmlElement("你的日期属性名")] public string 你的日期属性名Serialize { get => 你的日期属性名.ToString("yyyy-MM-dd HH:mm:ss"); set => 你的日期属性名 = DateTime.Parse(value); }
方案3:全局控制序列化行为(不改实体类)
如果实体类无法修改,可以在序列化时使用XmlWriter设置日期序列化规则:
public static string ConvertToXmlDoc(object dataModeldata) { Type modelType = dataModeldata.GetType(); var serializer = new XmlSerializer(modelType); var settings = new XmlWriterSettings { Indent = true, Encoding = System.Text.Encoding.UTF8, DateTimeHandling = DateTimeHandling.RoundtripKind }; using (var sw = new StringWriter()) using (var writer = XmlWriter.Create(sw, settings)) { serializer.Serialize(writer, dataModeldata); return sw.ToString(); } }
内容的提问来源于stack exchange,提问作者Adrian Jones
相关产品推荐
相关产品推荐

