从数据库中查询 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 值的字符串字段进行范围查询

关于SQLite数据库 字段 DateTime 类型

无法更新 MSSQL Server 中的 DateTime 字段

在 FileNet 内容引擎中仅使用日期查询 DateTime 字段

Mysql时间字段格式如何选择,TIMESTAMP,DATETIME,INT?

来自带有时区的 SQL Server 的 DateTime