日期时间序列化与数据库存储

在软件开发中,经常需要将对象序列化成XML格式,然后存储到数据库中。对于层次结构的数据对象,如订单和订单行,这种方法尤其有用。本文不讨论这种方法的优缺点,而是提供一个解决方案,用于处理在序列化过程中传递System.DateTime值的问题。

首先,让来探讨一下DateTime值的问题。假设有一个类,如下所示:

public class MyClass { public DateTime LocalDateTime { get; set; } }

这个类只暴露了一个属性,用于保存本地日期和时间。如果将其设置为DateTime.Now并序列化整个对象,LocalDateTime的值可能看起来像这样:

2010-01-17T12:29:23.5561314+02:00

现在,如果想要将这个字符串转换为SQL Server中的DATETIME类型(这就是在存储过程中解析序列化对象的XML时所做的),会得到一个错误消息:

Conversion failed when converting datetime from character string.

经过一些尝试,发现尝试转换的字符串不能包含时区信息,并且只支持毫秒。如果尝试执行这个语句:

SQL select cast('2010-01-17T12:29:23.556' as DateTime)

...它会很好地转换。因此,需要去掉时区信息,并将数字减少到只有毫秒。第一个很容易。在DateTime setter中,使用以下代码:

localDateTime = DateTime.SpecifyKind(value, DateTimeKind.Utc);

这将使DateTime值成为UTC时间,这意味着时区是+00:00,并且在序列化后,值现在将变为:

2010-01-17T12:29:23.5561314Z

这为提供了没有时区信息的本地时间。不用担心结尾的‘Z’。它对SQL Server来说是完全没问题的。如果想先将时间转换为UTC,可以使用:

utcDateTime = DateTime.SpecifyKind(value.ToUniversalTime(), DateTimeKind.Utc);

DateTime.ToUniversalTime()将DateTime值转换为通用时间,其余的都是一样的。

现在只剩下毫秒问题了。出现在毫秒后面的数字是ticks。一个tick是10000毫秒,这是时间的最小单位。所以需要以某种方式去掉ticks信息。

由于一个毫秒是10000个ticks,要去掉DateTime的ticks部分(使其等于0),可以将ticks除以10000,然后将结果乘以10000。System.DateTime结构还提供了一个方便的构造函数,它接受ticks的数量和DateTimeKind值来构建新的DateTime。所以可以使用它像这样:

localDateTime = new DateTime(value.Ticks / 10000 * 10000, DateTimeKind.Utc);

...当序列化时,值看起来像这样:

2010-01-17T12:29:23.556Z

这现在非常适合在SQL Server中使用。

不确定这是处理序列化输出的ticks部分的最快和最好的方法。然而,如果只需要日期,可以使用DateTime.Date结合DateTimeKind.Utc,输出将完全符合SQL Server的需要,就不需要处理ticks了。

using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Xml.Serialization; namespace DateTimeSerialization { public class MyClass { private DateTime localDateTime; private DateTime utcDateTime; public DateTime LocalDateTime { get { return localDateTime; } set { localDateTime = new DateTime(value.Ticks / 10000 * 10000, DateTimeKind.Utc); } } public DateTime UtcDateTime { get { return utcDateTime; } set { long ticks = value.ToUniversalTime().Ticks / 10000 * 10000; utcDateTime = new DateTime(ticks, DateTimeKind.Utc); } } } class Program { static void Main(string[] args) { MyClass myClass = new MyClass(); DateTime dateTime = DateTime.Now; myClass.LocalDateTime = dateTime; myClass.UtcDateTime = dateTime; StringBuilder builder = new StringBuilder(); StringWriter writer = new StringWriter(builder); XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); serializer.Serialize(writer, myClass); Console.WriteLine(builder.ToString()); Console.Read(); } } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485