【问题标题】:Timestamp in header as Byte array to DateTime标头中的时间戳作为字节数组到 DateTime
【发布时间】:2017-07-20 11:52:17
【问题描述】:

所以我目前被困在“简单”的事情上。我从第三方获得固定长度为 1024 字节的数据包。这包括 24 字节的数据包头和 1000 字节的有效载荷数据。为了获得时间戳,我必须查看某个索引。自 2000 年 1 月以来,时间戳记以秒为单位,它位于位置 8 和 4 字节长,毫秒位于位置 5 和 3 字节长。真实交易示例:

到目前为止,这很容易。现在我想检索这些值,以便我可以转换为 DateTime 对象,这样我就可以计算东西了。

时间戳记为自 2000 年 1 月以来的总秒数很简单:

'TimestampS_F is an byte array of 24 bytes long.

''' <summary>
''' Convert the total seconds since 1-1-2000 to the UTC time
''' </summary>
Private Function ConvertTimestampString(TimestampS_F As Byte()) As String
    Return New DateTime(2000, 1, 1, 0, 0, 0).AddSeconds(BitConverter.ToUInt32(TimestampS_F, 8)).ToString("yyyy-MM-dd HH:mm:ss:ffff") '.AddMilliseconds(BitConverter.ToUInt32(TimestampS_F, 5))
End Function 

但是知道毫秒时间戳,这是我被卡住的地方,因为该值是 3 个字节长,所以我无法将其转换为 Uint32 或 16。什么是正确的转换?

编辑: 我现在知道是什么创建了时间戳。这是一个 Spartan 芯片,正如文件所述,时间戳如下: S8 A 半小时调整时区(注意这是已签名的) U24 F 小数秒 U32 S 自格林威治标准时间 2000 年 1 月 1 日 00:00:00 以来的秒数 F / (2 ^ 24) 是秒的分数,所以总时间是 S + (A*30*60) + (F / (2^24))

编辑 25-08-2017:

直到今天才有时间继续这个话题。我仍然被卡住了,但我设法获得了更多文档。以下是:

DWORD tsFractionalAndAdjustment; // Timestamp - first 8 bits are our GMT adjustment in half-hours. signed char format
                                 // Timestamp - next 24 bits are the fractional part of the timestamp.

DWORD tsSeconds;      // Timestamp - Seconds since Jan 2000

现在查看上面的示例数组以及文档中的更多信息,事实证明我们必须从字节 4 到 8 开始。然后前 8 位用于 GMT 偏移量,最后 24 位用于我们拥有的小数秒应用公式:F / (2 ^ 24)。然而,如何在 C# 或 VB.net 中做到这一点?我知道&lt;&lt;&gt;&gt; 运算符,但找不到任何好的解释...

【问题讨论】:

    标签: c# vb.net timestamp


    【解决方案1】:

    那不编码为毫秒。我之前的回答是无效的。您将使用公式 (F*1000)/(2^24) 获得毫秒部分。读取 UInt32 中的字节 5-8,然后

    ms = ((ui32 & 0xffffff) * 1000.0) / (2 ^ 24)
    

    给你毫秒。这是一个浮点表达式,计算不适合 UInt32。

    编辑:

    在你的例子中:

    A = 0 //无时区调整,时间为 GMT(字节 4)

    S = 32*16777216 + 72*65536 + 19*256 + 203 = 541594571 //整秒,预期超过17年(字节8-11)

    F = 57*65536 + 29*256 + 96 = 3743072 //代表小数秒(字节5-7)

    F*1000 //代表整数毫秒和小数毫秒

    毫秒 = F*1000/(2^24) = 223,1044769287109375

    计算的 C# 代码是:

    UInt32 A = TimestampS_F[4] * 30 * 60; // zone adjustment in seconds
    UInt32 S = BitConverter.ToUInt32(TimestampS_F, 8); // whole seconds
    UInt32 F = BitConverter.ToUInt32(TimestampS_F, 5); // byte 5-8 (highest byte not needed)
    double ms = ((double)(F & 0xffffff) * 1000) / Math.Pow(2, 24); // milliseconds (cut highest byte, do conversion to milliseconds)
    DateTime dt = New DateTime(2000, 1, 1, 0, 0, 0).AddSeconds(A + S).AddMilliseconds(ms); // decoded result in local time
    

    不要使用位移运算符。您将损失小数毫秒。

    【讨论】:

    • 你成功了吗?
    • Hey Janos,好久不见(别忙了)今天我拿起这个话题,仍然遇到困难。但是我确实检索了更多文档,请参阅第一次发布的编辑
    【解决方案2】:

    我会尝试 Int16。

    查看您的真实示例,字节 5-7 似乎不可能包含毫秒的实际值。范围应为适合 Int16 的 0-999,最高字节应为 0。不是。

    【讨论】:

    • 感谢您的帮助。我试过没有运气。但是我知道是什么创建了时间戳。这是一个 Spartan 芯片,正如文档所述,时间戳如下:S8 A Adjustment for timezones in half-hours (note this is signed) U24 F Fractional seconds U32 S Seconds since 00:00:00 1st Jan 2000 in GMT F / (2 ^ 24) is the fraction of seconds, so the total time is S + (A*30*60) + (F / (2^24)) 也尝试过此操作,但无法将值转换为 DateTime 对象..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 2022-01-24
    • 2016-07-10
    • 2010-11-19
    • 2018-01-04
    相关资源
    最近更新 更多