6

我有一个 .NET WCF 服务,其中包含一些需要 DateTimeOffset 的操作合同。这样做是为了避免与 DST 和时区混淆。

但是,我怀疑使用 DateTimeOffset 毕竟是一个好主意,因为它是相当非标准的,并且会导致任何尝试连接的人头疼,例如,绑定到旧 .NET 版本的 Java 应用程序或 .NET 应用程序.

另一种方法是期望 UTC 日期时间,但这会带来有人会忘记使用 UTC 时间并使用本地时间调用服务的风险。我还可以期待一个本地时间 DateTime,因为客户端将始终处于同一时区,但这会在 DST 更改方面留下一些微妙但经典的模糊性。

是否有人对服务接口中的 DateTimeOffset 感到头疼,或者毕竟使用起来相对没有问题?

4

2 回答 2

9

我目前正在将我们的一些基础架构更改为 WCF,并偶然发现了这个悬而未决的问题并决定尝试一下。:)

WCF 序列化的方式,DateTime似乎DateTimeOffset有点奇怪。如以下示例所示,使用DateTime其他平台时使用看起来是更好的选择:

using System;
using System.Runtime.Serialization;
using System.ServiceModel;

[ServiceContract]
public class DateTimeOffsetService
{
    [OperationContract]
    public Container DoWork()
    {
        return new Container
        {
            NowDateTime = DateTime.Now,
            UtcNowDateTime = DateTime.UtcNow,
            NowDateTimeOffset = DateTimeOffset.Now,
            UtcNowDateTimeOffset = DateTimeOffset.UtcNow
        };
    }
}

[DataContract]
public class Container
{
    [DataMember]
    public DateTime NowDateTime { get; set; }

    [DataMember]
    public DateTime UtcNowDateTime { get; set; }

    [DataMember]
    public DateTimeOffset NowDateTimeOffset { get; set; }

    [DataMember]
    public DateTimeOffset UtcNowDateTimeOffset { get; set; }
}

请求的响应 XML 为:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
  <s:Body>
    <DoWorkResponse xmlns="http://tempuri.org/">
      <DoWorkResult xmlns:a="http://schemas.datacontract.org/2004/07/RD.MES.WcfService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:NowDateTime>2012-03-23T15:59:47.8328698+01:00</a:NowDateTime>
        <a:NowDateTimeOffset xmlns:b="http://schemas.datacontract.org/2004/07/System">
          <b:DateTime>2012-03-23T14:59:47.8328698Z</b:DateTime>
          <b:OffsetMinutes>60</b:OffsetMinutes>
        </a:NowDateTimeOffset>
        <a:UtcNowDateTime>2012-03-23T14:59:47.8328698Z</a:UtcNowDateTime>
        <a:UtcNowDateTimeOffset xmlns:b="http://schemas.datacontract.org/2004/07/System">
          <b:DateTime>2012-03-23T14:59:47.8328698Z</b:DateTime>
          <b:OffsetMinutes>0</b:OffsetMinutes>
        </a:UtcNowDateTimeOffset>
      </DoWorkResult>
    </DoWorkResponse>
  </s:Body>
</s:Envelope>

我在 GMT+01.00 时区,所以这些值似乎是正确的。为什么会这样?好吧,WSDLContainer是这样定义的:

<xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/WcfService">
    <xs:import schemaLocation="http://localhost:3608/DateTimeOffsetService.svc?xsd=xsd3" namespace="http://schemas.datacontract.org/2004/07/System"/>
    <xs:complexType name="Container">
        <xs:sequence>
            <xs:element minOccurs="0" name="NowDateTime" type="xs:dateTime"/>
            <xs:element minOccurs="0" name="NowDateTimeOffset" type="q1:DateTimeOffset"/>
            <xs:element minOccurs="0" name="UtcNowDateTime" type="xs:dateTime"/>
            <xs:element minOccurs="0" name="UtcNowDateTimeOffset" type="q2:DateTimeOffset"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="Container" nillable="true" type="tns:Container"/>
</xs:schema>

并且DateTimeOffset- 在 WSDL 中 - 定义为:

<xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/System">
    <xs:import schemaLocation="http://localhost:3608/DateTimeOffsetService.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
    <xs:complexType name="DateTimeOffset">
        <xs:annotation>
            <xs:appinfo>
                <IsValueType>true</IsValueType>
            </xs:appinfo>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="DateTime" type="xs:dateTime"/>
            <xs:element name="OffsetMinutes" type="xs:short"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="DateTimeOffset" nillable="true" type="tns:DateTimeOffset"/>
</xs:schema>

所以基本上,DateTime被序列化为标准xs:dateTime(它确实具有正确的时区组件)并被DateTimeOffset序列化为非标准的复杂类型,调用者必须正确理解和处理。

FWIW;既然我发现了这一点,我可能会使用DateTimeWCF 接口,除非我真的需要处理不同的时区偏移。

目前,我可以看到支持使用复杂类型的唯一理由(因为xs:dateTime应该能够包含它所做的所有信息!)是如果xs:dateTime已用于序列化DateTimeand DateTimeOffset,WCF 客户端将不知道使用哪种类型.

于 2012-03-23T15:43:30.470 回答
1

恕我直言,将 DateTime 与 WCF 服务一起使用的最大麻烦是 WCF 当前不支持 xs:Date - 请参阅此相关问题和链接的连接建议。

DateTimeOffset 对这个问题没有帮助。

于 2012-02-07T07:29:22.343 回答