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

时间:2012-03-06 21:00:00

标签: c# datetime

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

<00> 00 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异常。解析这个的正确方法是什么?

3 个答案:

答案 0 :(得分:5)

您确定这些值不是实际

DE A4 4F 4F 00 00 00 00

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

这会更有意义,并且代表一个小端的64位整数,你可以这样转换:

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位整数,以big-endian顺序排列以创建64位整数,那么你可以使用:

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

答案 1 :(得分:0)

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

How to convert a Unix timestamp to DateTime and vice versa?

答案 2 :(得分:-1)

  

解析此问题的正确方法是什么?

解析这个“正确”需要知道二进制数据的存储方式,以及它所代表的内容。

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

作为一个单独的问题,这句话:

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

可以更有效地写作:

BitConverter.ToInt32(bytes, index + 4)

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