.NET 3.5中DateTime序列化的最佳做法

时间:2020-03-05 18:54:08  来源:igfitidea点击:

大约4年前,我按照这篇MSDN文章介绍了DateTime使用最佳实践,该最佳实践是在.Net 1.1和ASMX Web服务(以SQL 2000服务器为后端)上构建.Net客户端的。我仍然记得DateTime遇到的序列化问题以及在不同时区的服务器所花费的测试工作。

我的问题是:是否为WCF和SQL Server 2008等某些新技术提供了类似的最佳实践文档,尤其是添加了新的datetime类型来存储时区感知信息。

这是环境:

  • 太平洋时间的SQL Server 2008.
  • Web服务层位于其他时区。
  • 客户端可能在不同时区使用.Net 2.0或者.Net 3.5. 如果这很容易,我们可以强迫所有人升级到.Net 3.5. :)

有关在每个层中使用的数据类型的任何好的建议/最佳实践?

解决方案

回答

我认为最好的方法是始终将对象作为UTC传递,并在客户端上转换为本地时间。这样,所有客户都有一个共同的参考点。

若要转换为UTC,请在DateTime对象上调用ToUniversalTime。然后,在客户端上,调用ToLocalTime以获取其当前时区。

回答

我很幸运,只保留了DateTime数据类型并将其始终存储为GMT。在每一层中,我都会将GMT值调整为该层的本地值。

回答

只要Web服务层和客户端层使用.NET DateTime类型,它就应该正确地序列化和反序列化为带有时区信息的SOAP标准本地日期/时间,例如:

2008-09-15T13:14:36.9502109-05:00

如果绝对要肯定要知道时区本身(即上面的时间可能是东部标准时间或者中部夏令时),则需要创建自己的数据类型以将这些数据段公开如下:

[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>

回答

UTC / GMT在分布式环境中将保持一致。

重要的一件事是在使用数据库中的值填充DateTime属性后指定datetimeKind。

dateTimeValueUtcKind = DateTime.SpecifyKind(dateTimeValue, DateTimeKind.Utc);

参见MSDN

回答

一个大问题是WCF序列化不支持xs:Date。这是一个很大的问题,好像我们只需要一个日期,就不应该让我们担心时区。以下连接问题讨论了一些问题:http://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=349215

如果要明确表示一个时间点,即不仅仅是日期部分,则如果客户端和服务器上都装有.NET 3.5,则可以使用DateTimeOffset类。或者为了实现互操作性,请始终将日期/时间值作为UTC传递。