【问题标题】:NAV RecordIDs in SQL - decoding date from hex stringSQL 中的 NAV RecordIDs - 从十六进制字符串解码日期
【发布时间】:2014-11-14 19:12:26
【问题描述】:

我正在尝试对表的记录 ID 进行逆向工程,当我将日期字段作为记录 ID 的一部分时遇到了障碍:

我的一条测试记录的记录 ID 是:

0x027D89000089FF4150303130353539000089FF4D43564100002E537116000000

解码如下:

0x027D8900 是 little endian 中的表 ID,解析为 9010434(我的表 id)

0x0089指的是“代码”数据类型

0xFF表示我的key包含字符

0x415030313035353900 是我的第一个主键,使用简单的 varchar 转换正确解析为 AP010559

下一部分与第二个主键相同,并且都使用 cast 正确解析

但是我在使用 002E537116000000 时遇到了问题,它指的是一个日期,并且像这样分解。

0x002E - “日期”数据类型

0x53711600 - 日期,应该解析为 2013-06-17,但我不知道如何,注意最后一个字节只是一个终止

0x0000 - 2 个空字节

相关链接:

NAV 数据类型:http://blogs.msdn.com/b/nav/archive/2010/09/03/table-data-type-values-used-in-record-links.aspx

RecordID 的结构:http://blogs.msdn.com/b/microsoft_dynamics_nav_sustained_engineering/archive/2009/08/06/how-do-record-links-encode-their-data-in-sql-server.aspx

提前感谢您的任何指导

【问题讨论】:

    标签: hex reverse-engineering microsoft-dynamics


    【解决方案1】:

    解码日期字段确实很棘手。

    它实际上是自支持的最早日期 (03-01-01) 以来的天数,但乘以 2(因为偶数对应于正常日期,奇数 - 对应于结束日期),并且对于特殊值。

    计算方法如下(PowerShell 中的示例):

    $days = [Convert]::ToInt32("167153", 16)
    $datetime = new-object System.DateTime(((($days - 737) / 2) + 2) * [TimeSpan]::TicksPerDay)
    Write-Host $datetime
    

    NAV 中的日期类型存储为 Int32,因此最后一个字节不是终结符,而是小端序中 Int32 值的第一个字节。但是,由于最大可能的日期值是 C31-12-9999,对应于 0x92766F00,因此该字节在日期值中始终为 0。

    737 是支持的最小日期 (03-01-0001)。低于此范围的是未定义日期 (0D),以及其他一些特殊常量,例如最短日期、最短结束日期。

    【讨论】:

    • 感谢您的回答,只需一个查询,在您的回答中,您通过将“167153”转换为 Int32 来获得天数的值,您从哪里得到 167153?
    • 我从你的问题中得到了它。您要转换的值是 0x53711600。它是小端表示法的 Int32,因此在处理之前应将其还原。
    • 顺便说一句,如果将 RecordID 读入字节数组,则可以使用 BitConverter:[Byte[]]$byteArray = @(0x53,0x71,0x16,0x00) $days = [Convert]: :ToInt32([BitConverter]::ToInt32($byteArray), 16) $datetime = new-object System.DateTime(((($days - 737) / 2) + 2) * [TimeSpan]::TicksPerDay) 写-主持人 $datetime
    • 什么是最短日期和最短截止日期?我从来没有听说过那些。 :-)
    【解决方案2】:

    这是 Alexander Drogin 使用 SQL 提供的解决方案的实现

    解码日期:

    DATEADD(Day, (convert(int, CAST(REVERSE(0xB5721600) as varbinary))-737)/2, CAST('0001-01-03' as date)) AS [DecodedDate]
    

    编码日期:

    CAST(REVERSE(CAST((DATEDIFF(Day, cast('0001-01-03' as date), cast('2013-12-11' as date))*2)+737 as varbinary)) as varbinary) AS [EncodedDate]
    

    经过测试并使用 NAV 2009

    【讨论】:

      猜你喜欢
      • 2018-08-21
      • 2020-11-11
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      • 2019-01-02
      • 2020-10-23
      相关资源
      最近更新 更多