WCF 日期时间偏移兼容性

发布于 2025-01-03 07:46:28 字数 368 浏览 0 评论 0原文

我有一个 .NET WCF 服务,其中包含一些采用 DateTimeOffset 的操作合约。这样做的目的是避免与 DST 和时区产生任何混淆。

然而,我怀疑使用 DateTimeOffset 毕竟是一个好主意,因为它相当不标准,并且会给任何试图连接 Java 应用程序或绑定到旧 .NET 版本的 .NET 应用程序的人带来麻烦。 。

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

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

I have a .NET WCF service with a few operation contracts that takes a DateTimeOffset. The idea is to avoid any confusion with DST and time zones.

However I am in doubt that using DateTimeOffset is a good idea after all, since it is fairly non-standard and would cause headaches for anyone trying to connect with, say, a Java application or a .NET application bound to an older .NET version.

An alternative is to expect a UTC DateTime, but this introduces the risk that someone will forget to use UTC time and call the service with a local time.
I could also expect a local time DateTime, since clients will always be in the same timezone, but this leaves some subtle, but classic, ambiguity around DST changes.

Does anyone have headache stories with DateTimeOffset in a service interface or is it relatively unproblematic to use after all?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

九八野马 2025-01-10 07:46:28

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

WCF 序列化 DateTimeDateTimeOffset 的方式似乎有点奇怪。如以下示例所示,在与其他平台一起使用时,使用 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>

I'm in the GMT+01.00 timezone, so the value might be right 。为什么会这样呢?那么,WSDL 定义 Container 如下:

<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 被序列化为标准 < code>xs:dateTime (它确实具有正确的时区组件)和 DateTimeOffset 被序列化为非标准复杂类型,调用者必须正确理解和处理该类型。

FWIW;由于我发现了这一点,我可能会使用 DateTime 作为 WCF 接口,除非我实际上需要处理不同的时区偏移。

目前,我认为支持使用复杂类型的唯一理由(因为 xs:dateTime 应该能够包含它所包含的所有信息!)是如果 xs:dateTime code> 用于序列化 DateTimeDateTimeOffset,WCF 客户端不知道要使用哪种类型。

I'm currently changing some of our infrastructure to WCF and stumbled upon this unanswered question and decided to try it. :)

The way that WCF serializes DateTime and DateTimeOffset seems to be a bit weird. As the following sample shows, using DateTime looks like the better option when working with other platforms:

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; }
}

The response XML of the request is:

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

I'm in the GMT+01.00 timezone, so the values seem about right. Why is it this way? Well, the WSDL defines Container like this:

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

And DateTimeOffset - in WSDL - is defined as:

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

So basically, DateTime is serialized as a standard xs:dateTime (which does have the correct timezone component) and DateTimeOffset is serialized into a non-standard complex type, which the caller would have to understand and handle correctly.

FWIW; Since I found this out, I will probably use DateTime for the WCF interface unless I actually need to take care of different timezone offsets.

Currently, the only justification I could see in favour of using the complex type (since xs:dateTime should be able to contain all information that it does!) is that if xs:dateTime had been used to serialize DateTime and DateTimeOffset, a WCF client would have no idea which type to use.

软甜啾 2025-01-10 07:46:28

恕我直言,在 WCF 服务中使用 DateTime 时最令人头痛的是 WCF 目前不支持 xs:Date - 请参阅 此相关问题以及链接的 Connect 建议。

DateTimeOffset 对解决这个问题没有帮助。

IMHO the biggest headache in using DateTime with a WCF Service is that WCF doesn't currently support xs:Date - see this related question and the linked Connect suggestions.

DateTimeOffset doesn't help with this problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文