如何将8字节十六进制转换为DateTime

本文关键字:转换 DateTime 十六进制 字节 | 更新日期: 2023-09-27 18:27:02

我正在尝试解析一个文件,该文件的时间戳我认为是8字节长,在十六进制中看起来是这样的

00 00 00 DE A4 4F 4F

当我将其解析为Int64时,我没有收到正确的日期/时间。然而,如果我跳过前4个字节,然后做一些类似的事情,我就会得到正确的日期时间。

TimeSpan span = TimeSpan.FromTicks(BitConverter.ToInt32(bytes.Skip(index).Take(8).ToArray(),4) * TimeSpan.TicksPerSecond);
DateTime t = new DateTime(1970, 1, 1).Add(span);
StartTime = TimeZone.CurrentTimeZone.ToLocalTime(t);

然而,我不确定我要解析的下一个文件的前4个字节是否会有前导00。如果我将其解析为ToInt64,我将抛出outOfRange异常。解析这个的正确方法是什么?

如何将8字节十六进制转换为DateTime

你确定这些值实际上不是

DE A4 4F 4F 00 00 00 00

例如,由于您在文件中的位置计算错误?

这将更有意义,并且表示一个64位的小endian整数,您可以这样转换:

static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0,
                                              DateTimeKind.Utc);
...
long seconds = BitConverter.ToInt64(data, index);
DateTime date = Epoch + TimeSpan.FromSeconds(seconds);

(顺便说一句,请注意,这个转换代码要简单得多——既不干扰LINQ,也不通过TicksPerSecond对值进行多路复用。)

编辑:如果真的两个小端32位整数,按大端顺序排列以创建64位整数,那么您可以使用:

ulong x = BitConverter.ToUInt32(data, index);
ulong y = BitConverter.ToUInt32(data, index + 4);
ulong combined = (x << 32) | y;
long seconds = unchecked ((long) combined);

根据如何从数据中获取有效的DateTime,它看起来非常像POSIX time_t格式:自1970年1月1日以来的秒数,存储为64位整数值。关于如何将其中一个转换为DateTime,有几个相关的问题。看看这是否对你有帮助:

如何将Unix时间戳转换为DateTime,反之亦然?

解析这个的正确方法是什么?

要"正确地"解析这个数据,需要了解二进制数据是如何存储的,以及它到底代表了什么。

在您的情况下,听起来它必须被解析为Int32。在所有情况下,您都需要确定适当的填充。如果事先不知道二进制流中数据的结构,就无法"知道"如何"正确"解析二进制流。

作为一个单独的问题,本声明:

BitConverter.ToInt32(bytes.Skip(index).Take(8).ToArray(),4)

可以更有效地写成:

BitConverter.ToInt32(bytes, index + 4)

在这种情况下使用LINQ只会使操作效率非常低,因为ToInt32已经提供了偏移。