.NET 3.5 中日期时间序列化的最佳实践
-
09-06-2019 - |
题
大约四年前,我遵循了这个 MSDN 文章 有关在 .Net 1.1 和 ASMX Web 服务(以 SQL 2000 服务器作为后端)上构建 .Net 客户端的 DateTime 使用最佳实践。我仍然记得 DateTime 遇到的序列化问题以及对不同时区的服务器进行的测试工作。
我的问题是这样的:对于 WCF 和 SQL Server 2008 等一些新技术,是否有类似的最佳实践文档,特别是添加了用于存储时区感知信息的新日期时间类型。
这是环境:
- SQL Server 2008(太平洋时间)。
- Web 服务层位于不同的时区。
- 客户端可以在不同时区使用.Net 2.0 或.Net 3.5。如果方便的话,我们可以强制每个人升级到 .Net 3.5。:)
对于每层使用的数据类型有什么好的建议/最佳实践吗?
解决方案
我认为最好的方法是始终将对象作为 UTC 传递,并在客户端上转换为本地时间。通过这样做,所有客户都有一个共同的参考点。
要转换为 UTC,请对 DateTime 对象调用 ToUniversalTime。然后,在客户端上调用 ToLocalTime 以获取当前时区的时间。
其他提示
一个大问题是 WCF 序列化不支持 xs:Date。这是一个大问题,就好像您想要的只是一个约会,您不应该被迫关心时区。以下连接问题讨论了一些问题: http://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=349215
如果你想明确地表示一个时间点,即不仅仅是日期部分,如果客户端和服务器上都有 .NET 3.5,则可以使用 DateTimeOffset 类。或者为了实现互操作性,始终将日期/时间值传递为 UTC。
UTC/GMT 在分布式环境中将保持一致。
一件重要的事情是,在使用数据库中的值填充 DateTime 属性后指定 datetimeKind。
dateTimeValueUtcKind = DateTime.SpecifyKind(dateTimeValue, DateTimeKind.Utc);
只要您的 Web 服务层和客户端层使用 .NET DateTime 类型,它就应该正确序列化和反序列化为带有时区信息的 SOAP 标准本地日期/时间,例如:
09/15/2008 20:14:36
如果您绝对、肯定必须知道时区本身(即上面可能是东部标准时间或中部夏令时间),您需要创建自己的数据类型来公开这些片段:
[Serializable]
public sealed class MyDateTime
{
public MyDateTime()
{
this.Now = DateTime.Now;
this.IsDaylightSavingTime = this.Now.IsDaylightSavingTime();
this.TimeZone = this.IsDaylightSavingTime
? System.TimeZone.CurrentTimeZone.DaylightName
: System.TimeZone.CurrentTimeZone.StandardName;
}
public DateTime Now
{
get;
set;
}
public string TimeZone
{
get;
set;
}
public bool IsDaylightSavingTime
{
get;
set;
}
}
那么你的回应将如下所示:
<Now>2008-09-15T13:34:08.0039447-05:00</Now>
<TimeZone>Central Daylight Time</TimeZone>
<IsDaylightSavingTime>true</IsDaylightSavingTime>
我很幸运,只保留了 DateTime 数据类型并始终将其存储为 GMT。在每一层中,我会将 GMT 值调整为该层的本地值。