毫秒值未保存在 SQL Server 日期时间列中

本文关键字:日期 Server 时间 SQL 存在 保存 | 更新日期: 2023-09-27 18:37:12

我需要存储一个 DateTime 值,该值从使用 DateTime.UtcNow 的 C# 应用程序发送到数据库。如果我将其保存到日期时间列,毫秒值始终为 000。但是,从应用程序进行调试时,毫秒值将从应用程序发送到数据库。我错过了什么?

毫秒值未保存在 SQL Server 日期时间列中

这可能是因为datetime列舍入毫秒部分。来自文档;

准确性

四舍五入为 .000.003.007 秒的增量

由于您没有向我们展示存储UtcNow值的频率(我假设您将其存储为DateTime,而不是字符串表示,因为无参数ToString和其他标准格式通常不会生成毫秒部分),这可能会发生,但如果您在短时间间隔内执行此操作,总是四舍五入为毫秒部分000真的很奇怪。但是,当然,我们还不能知道。

另一方面,datetime2类型不进行任何舍入。它的精度是100纳秒。

准确性

100 纳秒

这里没有愉快的使用Datetime因为

SQL Server 仅将时间存储到大约 1/300 秒。 这些始终落在 0、3 和 7 毫秒

SQL Server 2008 具有更高的精度。datetime2数据类型将准确存储如下值:2008-12-19 09:31:38.5670514

请参阅参考文档

在我看来

,某事/某人正在执行默认的ToString,而不是使用具有正确ISO标准格式的ToString。

日期与时间的正确 ISO 格式是

yyyy-MM-ddTHH:mm:ss.fff

而仅日期 ISO 格式是

yyyyMMdd

您可以检查:

static void Main(string[] args)
{
    System.DateTime cur = System.DateTime.UtcNow;
    string strDefault = cur.ToString();
    string str  = cur.ToString("yyyy-MM-ddTHH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture);
    System.Console.WriteLine(str);
    System.Console.WriteLine(strDefault);
}

这输出

2016-03-03T08:31:27.324
03.03.2016 08:31:27

您可能还希望使用 HEX 格式,因为这可以提高精度,或者至少保留 SQL-Server 中已有的值。如果不使用十六进制表示形式,则可以从 SQL 服务器获取 23:59:59.997 值并重新保存,并且使用 day+1 将获得 00:00:00。使用十六进制格式将保留 .997,而保存 ISO 字符串将产生 day+1。

public static string GetTimeAsHex(System.DateTime dt)
{
    System.DateTime zero = new System.DateTime(1900, 1, 1);
    System.TimeSpan ts = dt - zero;
    System.TimeSpan ms = ts.Subtract(new System.TimeSpan(ts.Days, 0, 0, 0));
    double x = System.Math.Floor(ms.TotalMilliseconds / 3.3333333333);
    string hex = "0x" + ts.Days.ToString("X8") + System.Convert.ToInt32(x).ToString("X8");
    return hex;
}

无论如何,正如其他人已经告诉您的那样,SQL 服务器日期时间仅精确到 4 毫秒的误差范围内。这就是为什么你应该使用 datetime2,因为它修复了日期时间中的许多问题(错误/"功能"),包括毫秒范围内的精度不足。

如果要将 INSERT 语句构建为 string ,请尝试在字符串转换中指定毫秒的输出

DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);