我们向客户提供WCF Web服务,允许他们将DateTime存储在SQL Server数据库中。 WSDL的摘录:
<xs:complexType name="TimePeriod">
<xs:sequence>
<xs:element minOccurs="0" name="endDateTime" nillable="true" type="xs:dateTime"/>
<xs:element minOccurs="0" name="startDateTime" nillable="true" type="xs:dateTime"/>
</xs:sequence>
例如,我的客户向我发送UTC日期时间:
<af:effectivePeriod>
<af:startDateTime>2018-01-16T10:32:28Z</af:startDateTime>
</af:effectivePeriod>
它存储在SQL Server数据库的datetime
字段中。
但是在读取服务的输出中,我没有UTC指示器:
<af:effectivePeriod>
<af:startDateTime>2018-01-16T10:32:28</af:startDateTime>
</af:effectivePeriod>
“ Z”是DateTimes的一种特例。文字“ Z”实际上是UTC时间的ISO 8601 DateTime标准的一部分。如果在时间结束时加上“ Z”(祖鲁语),则表示该时间为UTC,因此真正的Z是时间的一部分
我怎么可能在读取方法的输出处使用Z
?我是否需要修改存储在SQL Server中的数据类型?对服务的WSDL有影响吗?
答案 0 :(得分:1)
无论何时需要保持时间偏移,都应使用DateTimeOffset(.net和SqlServer)
在WCF数据合同中,您可以添加DateTimeOffset DataMember,但是它将对客户端产生影响,并且您的服务wsdl将会更改,因为将创建复杂类型的DateTimeOffset:
<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>
答案 1 :(得分:1)
Microsoft有explanation的说明如何将日期和时间与字符串转换为日期和时间;而您的问题(我将在下面介绍)是您丢失了Kind
。
DateTime
ToString
方法的“ o” standard format将为您提供所需的“往返”类型。
使用DateTime
中的RoundTripKind
Parse() with DateTimeStyles读回值。
您的DateTime
缺少“ Z”指示符这一事实意味着(如在“ o”的“标准格式”页面上所记录的)DateTime
的{{1}}是{{ 1}}。如果您已经从数据库中读取了这些Kind
,则Unspecified
将是DateTime
(在读取Kind
属性以确认后,您可以使用调试器对其进行检查这个)。
解决方法是,您必须知道要存储的Unspecified
种类,因此可以在阅读时设置种类(因为如果不这样做,则种类将会是未指定)。例如,如果您仅存储Kind
DateTime
UTC
,那么当您从数据库中读取它们时,可以在DateTime上适当地设置Kind
。您可以这样做:
DateTime
我有一个扩展方法可以将其封装起来,所以我可以简单地调用:
Kind
通过以下方式实现:
var myUtcDateTime = DateTime.SpecifyKind(myUnspecifiedDateTime, DateTimeKind.Utc);
或者您可以查看this answer来了解如何使用实体框架。
(请注意,这种方法适用于UTC;但是您不能决定对种类为var myDateTime = dataReader.GetUtcDateTime(ordinal);
的东西做同样的事情,因为不能保证您正在读取值的本地变量是(例如,夏令时可能刚刚开始或结束。)
但是我要说的是,如果您对实际时间真的很感兴趣,那么更好地解决问题的这种 (如果您原谅双关语!)是使用public static class DataReaderExtensions
{
public static DateTime GetUtcDateTime(this IDataReader reader, int ordinal)
{
var readDateTime = reader.GetDateTime(ordinal);
return DateTime.SpecifyKind(readDateTime, DateTimeKind.Utc);
}
}
。它们存储了DateTime和Offset,并确保您无需放入任何内容即可收回放入的内容。