从数据库中查询 DateTime 字段时,我可以控制 DateTimeKind 吗?
Posted
技术标签:
【中文标题】从数据库中查询 DateTime 字段时,我可以控制 DateTimeKind 吗?【英文标题】:When querying DateTime Fields from the DB, can I control the DateTimeKind? 【发布时间】:2017-08-30 20:44:32 【问题描述】:当我从 C# 查询涉及 DateTime
字段的 SqlServer 数据库时,返回的 System.DateTime
具有 Kind==Unspecified
这并不奇怪,因为 SqlServer DateTime
类型不保留时区信息。
我想知道是否有一种方法可以自动将这些值读取为本地或通用,而不是在读取查询结果后手动转换它们,这会在丢失字段时引入更多错误的可能性。
典型代码如下:
using (var conn = ...)
using (var command = ...)
conn.Open();
var reader = command.ExecuteReader();
while (reader.Read())
DateTime dateField = (DateTime)reader["date"];
//dateField.Kind == Unspecified
【问题讨论】:
据我所知,没有内置的方法可以做到这一点,但您可以轻松地为SqlDataReader
创建自己的扩展方法,然后调用reader.GetDateAsLocal("date")
和reader.GetDateAsUtc("date")
。跨度>
SQL server中存储DateTime时,不存储时区信息。因此,当您检索它时它不可用。您可以确保在将 DateTime 值存储到 db 之前将其转换为 UTC,或者使用 DateTimeOffset 将 DateTime 值存储在数据库中。
SQL Server 也有 datetimeoffset
类型,如果您不想要毫秒 (datetimeoffset2(0)
),它使用与 datetime
相同的 空间。使用datetimeoffset
而不是datetime
以避免猜测。 Local
无论如何都没有任何意义——对谁来说是本地的?数据库服务器、Web 服务器、浏览器?即使是偏移量也想防止所有问题 - 如果 DST 规则发生变化会发生什么?如果这是一个问题,请同时存储 IANA 时区并使用例如 NodaTime 来处理日期
@PanagiotisKanavos 这一切都很好,但“更改数据库”通常不是开发人员权限范围内的事情!
【参考方案1】:
DateTime dateField = DateTime.SpecifyKind((DateTime)reader["date"], DateTimeKind.Utc);
由于它没有保存在数据库中,您必须在您自己的代码中检索时指定它,尽管您可以创建扩展方法,但 DataReader 中没有快捷方法。
public static class Helper
public static DateTime GetDateTimeAsUtc(this IDataReader reader, string column)
return DateTime.SpecifyKind((DateTime)reader[column], DateTimeKind.Utc);
然后调用它
DateTime dateField = reader.GetDateTimeAsUtc("date");
【讨论】:
这是一个非常好的模式。感谢您对其进行编码。 +1。以上是关于从数据库中查询 DateTime 字段时,我可以控制 DateTimeKind 吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 BigQuery 中对具有 DateTime 值的字符串字段进行范围查询
无法更新 MSSQL Server 中的 DateTime 字段
在 FileNet 内容引擎中仅使用日期查询 DateTime 字段