标头中的时间戳作为Byte数组到DateTime

时间:2017-07-20 11:52:17

标签: c# vb.net timestamp

所以我现在已经陷入困境"简单"。我从第三方获得固定长度为1024字节的数据包。这包括24字节的包头和1000字节的有效载荷数据。为了获得时间戳,我必须查看某个索引。自2000年januari以来,时间戳以秒为单位记录,它位于8位和4位长的位置,毫秒位于位置5和3字节长。真实交易的例子: enter image description here

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

时间戳为januari 2000以来的总秒数很容易:

'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起GMT 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中完成?我知道<<>>运营商,但无法找到任何好的解释......

2 个答案:

答案 0 :(得分:0)

我会尝试Int16。

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

答案 1 :(得分:0)

那时没有编码为毫秒。我之前的回答是无效的。您将使用公式(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

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