我有一个.NET WCF服务,其中包含一些采用DateTimeOffset的操作协定。我们的想法是避免与夏令时和时区混淆。
然而,我怀疑使用DateTimeOffset毕竟是一个好主意,因为它是相当非标准的,并且会对任何试图连接的人造成麻烦,例如,Java应用程序或绑定到较旧版本的.NET应用程序.NET版本。
另一种方法是期望UTC DateTime,但这会带来某人忘记使用UTC时间并以本地时间调用服务的风险。 我还可以期待本地时间DateTime,因为客户端将始终处于相同的时区,但这会在DST更改时留下一些微妙但经典的模糊性。
有没有人在服务界面中使用DateTimeOffset头痛的故事,或者毕竟使用起来相对没有问题?
答案 0 :(得分: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时区,所以价值似乎是正确的。为什么会这样?好吧,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
被序列化为标准xs:dateTime
(具有正确的时区组件),DateTimeOffset
被序列化为非标准复杂类型,调用者将必须正确理解和处理。
FWIW;由于我发现了这一点,我可能会使用DateTime
作为WCF接口,除非我真的需要处理不同的时区偏移。
目前,我可以看到支持使用复杂类型的唯一理由(因为xs:dateTime
应该能够包含它所做的所有信息!)是因为xs:dateTime
已用于序列化DateTime
和DateTimeOffset
,WCF客户端不知道要使用哪种类型。
答案 1 :(得分:1)
恕我直言,将DateTime与WCF服务结合使用的最大问题是WCF目前不支持xs:Date - 请参阅this related question以及链接的Connect建议。
DateTimeOffset对此问题没有帮助。