如何将 [Log Content 0] 中的 fn_dblog() 详细信息中的 8 字节日期时间转换为 C# DateTime 对象?

How to convert 8 byte datetime from fn_dblog() details in [Log Content 0] into a C# DateTime object?

我删除了最近插入的一行数据。 我没有恢复和前滚这个巨大数据库的第二个副本来检索插入的数据,而是尝试使用 fn_dblog()“未记录”系统函数来检索它。 使用说明(在此处找到:https://sqlfascination.com/2010/02/03/how-do-you-decode-a-simple-entry-in-the-transaction-log-part-1/

[日志内容 0] 列的内容 fn_dblog() returns,我成功地从日志文件中检索了我插入(后来删除)的数据。在为固定宽度列数据保留的二进制数据部分,我发现 SQL DateTime 列值占用 8 个字节。我正在 .NET 程序中处理二进制数据,根据 Int 或 BigInt 值使用 BitConverter.ToInt64 或 BitConverter.ToInt32

我已经设法检索到我需要的所有插入列值,日期时间列除外...

我不清楚如何将 SQL DateTime 列的 8 个字节解释为 C# DateTime 对象。如果有帮助,下面是从特定日期时间的事务日志数据中检索到的日期时间 8 字节的十六进制和 Int64 版本示例。

二进制日期时间(大约 7/31/2020):0xF030660009AC0000(颠倒字节序:0x0000AC09006630F0)

作为 Int64:189154661380804

有什么建议吗?这是日期的内部 SQL 服务器表示,我不确定在哪里可以找到它的文档...

我终于找到了答案:存储为 VARBINARY 的 SQL DateTime(类似于我从事务日志中读取的字节)包含两个整数。第一个是日期部分 - 自 1/1/1900 以来的天数。较早的日期将为负数。

第二个整数是自午夜以来的毫秒数除以 3.33333333。

因为字节是按long倒序存储的,所以buffer中8个字节的前4个字节是分钟,第二个是日期。

这是我用来获取日期的代码片段。我一次 运行 通过固定长度字段,跟踪字节数组中的当前偏移量... 变量ba是[Log Content 0]列字节的字节数组

        int TimeInt;
        int DateInt;
        DateTime tmpDt;

        //initialize the starting point for datetime - 1/1/1900
        tmpDt = new DateTime(1900, 1, 1);
        // get the time portion of the SQL DateTime
        TimeInt = BitConverter.ToInt32(ba, currOffset);
        currOffset += 4;
        // get the date portion of the SQL DateTime
        DateInt = BitConverter.ToInt32(ba, currOffset);
        currOffset += 4;
        // Add the number of days since 1/1/1900
        tmpDt = tmpDt.AddDays(DateInt);
        // Add the number of milliseconds since midnight
        tmpDt = tmpDt.AddMilliseconds(TimeInt * 3.3333333);