使用哪种 SQL Server sql 数据类型来保留 UTC 日期时间

Posted

技术标签:

【中文标题】使用哪种 SQL Server sql 数据类型来保留 UTC 日期时间【英文标题】:Which SQL Server sql data type to use in order to preserve UTC date time 【发布时间】:2011-05-27 04:31:55 【问题描述】:

我有一个 SQL Server DB 表,其中有一列“ReceivedDate”定义为“datetime”,其中应包含 UTC 日期...在我的 C# 代码中,我使用实体框架将表映射到一个类,该类具有相应的System.DateTime 类型的属性“ReceivedDate”。

程序将 XML 文件中的日期加载到 DB 中,稍后会检查 XML 中的数据是否与 DB 中的数据相同...当 XML 和 DB 中的 ReceivedDate 日期不匹配时,检查失败。 ..例如:

ReceivedDate from XML:
<ReceivedDate>2010-12-16T22:53:27.5912217Z</ReceivedDate>

ReceivedDate from DB:
2010-12-16 22:53:27.590

经过一些调试,我注意到 DB 中的日期没有将 Kind 属性设置为 Utc,并且刻度数要少得多,因此日期比较失败...

如何在 SQL 中存储完整的 UTC 日期 服务器所以当实体框架 检索它,我得到 System.DateTime 与那个完全相同的值 来自 XML 文件(包括 Kind=Utc)? 这只是使用的问题吗 我的列的不同 sql 数据类型 (例如 datetime2 而不是 datetime)?

更新:

我解决这个问题的方法是:

    将 sql 数据类型更改为“datetime2”以匹配 sql 数据类型和 .net System.DateTime 之间的精度 在我的 POCO 中,我覆盖了 Equals,在检查 ReceivedDate 属性时,我刚刚从 ReceivedDate 创建了另一个 DateTime 变量,但使用了 Kind == Utc 的构造函数。

这可行,尽管我同意使用 DateTimeOffset 可能是更好的解决方案。

【问题讨论】:

【参考方案1】:

使用datetimeoffset 存储在 SQL Server 上。

定义一个日期,该日期与一天中具有时区意识且基于 24 小时制的时间相结合。

另外,请考虑在您的 .NET 代码中使用 DateTimeOffset 结构而不是 DateTime

【讨论】:

不幸的是,这对我来说不是一个选项......域模型属性设置为 System.DateTime,如果我使用“datetimeoffset”,正如你所指出的,我将不得不使用 System.DateTimeOffest ...我需要一个解决方案来使用 DateTime 保留 UTC(如果可能的话) 看来DateTimeOffset 结构只有在你 偏移量时才有用:即你使用SQL 的DateTimeOffset 或者你知道UTC 日期时间并且 时区。但是 +1 对于开发/改造新东西的人们来说是一个真正可行的选择。 @zam6ak,那么你的域模型是错误的。 EF 4 支持DateTimeOffset。更新您的模型。 @Craig Stuntz 有时,在现实生活中,您只是无法更改域模型(在我的例子中,域模型已在几年前建立)... @zam6ak:那么你不需要(EF)直接映射到它。您可以映射到正确的类型并投影到对象空间中的域模型上。【参考方案2】:

Sql server中的datetime只有an accuracy of one three-hundredth of a second。

.Net 中的准确率更高。因此,DB 数据是四舍五入的,而不是相同的。如果你看你的数据,误差是 0.0012217 秒。

如果可能,您可以使用datetime2:

0 到 7 位,精度为 100ns。默认精度为 7 位。

datetime2 使用与 .Net DateTime 相同的准确度。

【讨论】:

正如我所怀疑的(在我的问题中),精度是问题的一部分......更改为“datetime2”有帮助,但是实体框架仍然没有将 Kind 属性设置为“Utc”(根据到这个帖子:social.msdn.microsoft.com/Forums/en/adodotnetentityframework/…) 感谢您的澄清。我将您的回复设置为答案,因为它更符合我的用例。但是,如果我可以选择更改我的域模型,我会选择 @Oded 答案,因为 DateTimeOffset 可能是更优雅的解决方案。【参考方案3】:

如果您想将数据库 UTC DateTimes 转换为 C# DateTimes,请执行此操作。创建DateTime 时,使用带有DateTimeKind 参数的构造函数:

DateTime utcDateTime = new DateTime(((DateTime)row["myUtcDateTime"]).Ticks, DateTimeKind.Utc)

如果您正在寻找一种更好的方式在 SQL 中实际存储它(并且您在 2008 年),请遵循 @Oded 的建议。

【讨论】:

正如我在问题中提到的,我使用的是实体框架,所以我的域模型由 EF “管理” - 我不是自己“加载”日期... @zam,啊......好吧.....实体框架比切片面包更好! @zam6ak, @Brad:如果你坚持使用错误的数据类型——EF 和 SQL Server 都支持DateTimeOffset,如果你打算这样做,你应该使用混合异构时区——您仍然可以使用 EF 投影编写等效代码。但是如果你希望它是自动的,那么你必须使用正确的类型。 @Craig,我绝对同意在两种情况下(SQL 和 .NET)使用DateTimeOffset 是最好的方法。 @Craig Stuntz 我也同意你的观点,但正如我提到的,我的域模型是“一成不变的”(POCO 的集合),我无法更改它,所以我必须使用 DateTime。

以上是关于使用哪种 SQL Server sql 数据类型来保留 UTC 日期时间的主要内容,如果未能解决你的问题,请参考以下文章

C# 的哪种数据类型相当于 SQL Server 中的钱? [复制]

sql server 小数字段设为哪种类型?

我可以在我的开发机器上为 C# VS2010 项目使用哪种轻量级 SQL Server 类型?

如何选择 SQL Server 数据库的排序规则

SQL Server 自动确定来自 VARCHAR(MAX) 列的数据类型

OData Edm.GeographyPoint 在 SQL Server 数据库中指的是啥类型