【问题标题】:Extracting date and time from a binary data string using使用从二进制数据字符串中提取日期和时间
【发布时间】:2014-08-11 16:32:19
【问题描述】:

我有一个将时间序列数据存储为打包二进制文件的第三方应用程序。我正在尝试创建一个工具来转换存储在此文件中的数据。

下面显示的是这些数据的快照。

41 16 00 00 01 00 D7 11 00 00 01 00 E8 55 A6 20 08 1E D0 08 00 00 00 60 59 D5 
86 40 03 E8 F5 2C 22 08 1E D0 08 00 00 00 00 C0 0B 87 40 01 E8 95 B3 23 08 1E 
D0 08 00 00 00 40 1E 00 87 40 01 E8 35 3A 25 08 1E D0 08 00 00 00 60 13 F8 86
40 01 E8 D5 C0 26 08 1E D0 08 00 00 00 40 65 09 87 40 01 E8 75 47 28 08 1E D0 
08 00 00 00 20 8A F6 86 40 01 E8 15 CE 29 08

我知道这块数据对应以下值。

5/13/2013 17:46:11.558  730.6686401
5/13/2013 17:46:14.118  737.46875
5/13/2013 17:46:16.678  736.0147705

我可以提取值:它们是double 类型。比如00 00 00 60 59 D5 86 40这8个字节对应730.6686401

但我对如何提取日期时间格式感到困惑。我知道它被埋在这个字符串的某个地方。我怎样才能知道时间的格式是什么?

我一直在使用 Python 的 struct 模块进行类型转换。

有人有什么想法吗?

【问题讨论】:

  • 从其他 2 个浮点值来看,编码为双精度值,它们之间只有 9 个字节来编码日期时间值。
  • 此外,序列 [08 1E D0 08] 重复 6 次,始终相隔 13 个字节。此块中是否只有 3 个值,还是超过 3 个?
  • @aruisdante:我想说那里至少有 6 套。
  • 序列 [E8 X5] 也重复(在这种情况下为 7,但看起来这个块可能会被截断,并且会有另一个 08 1E 序列),其中 X 是一个可变数字,2 个字节08 1E序列之前
  • 8个字节够存储信息吗?

标签: python datetime struct reverse-engineering


【解决方案1】:

如果您在 double 之一之前取 8 个字节,并将其视为一个整数(低端,如双精度数),那么您会得到以下数字:

635040567715583464
635040567741183464
635040567766783464

如果您将这些数字除以 10**7,那么您将获得以秒数(和小数秒数)表示的日期。至少它对应于分钟、秒和秒的分数。在几个小时内,我得到一个由两个错误(时区?)。对于完整的日期,日期编号 735000(*) 对应于 2013 年 5 月 13 日,如下所示。这是从第 1 年开始的天数:

>>> datetime.date(1,1,1) + datetime.timedelta(735000)
datetime.date(2013, 5, 13)

(*) 是这些数字中的任何一个除以 10**7 * 60 * 60 * 24

或一步完成:

>>> x = 635040567715583464 / 10.**7 / 86400
>>> datetime.datetime(1,1,1) + datetime.timedelta(x)
datetime.datetime(2013, 5, 13, 15, 46, 11, 558353)

【讨论】:

  • datetime 支持序数 (datetime.datetime.fromordinal(735000))。所以这些数字是 1/1/1 00:00:00 纪元而不是 UNIX 纪元的偏移量?
  • 所以ordinal, rem = divmod(635040567715583464, 10**7 * 86400),然后datetime.datetime.fromordinal(ordinal) + datetime.timedelta(microseconds=rem/10.0) 给你正确的日期datetime.datetime(2013, 5, 12, 15, 46, 11, 558346),大概是UTC。
  • 我不确定fromordinal(735000) 到底做了什么,但结果是休息一天(12 号而不是 13 号)。当然最终的结果仍然是 2 小时的休息时间,所以也许我们真的应该使用fromordinal() 并考虑结果是 22 或 26 小时的休息时间。
  • fromordinal() 将整数解释为自 0001 年 1 月 1 日以来的天数。如果那里有一个错误的地方,应该很容易纠正。
  • 我挖掘了 2 小时的差异。可能是因为数据是在欧洲夏令时收集的。 @Armin Rigo,时间转换是否为我们提供了 UTC 时间?
猜你喜欢
  • 1970-01-01
  • 2013-06-14
  • 2020-08-14
  • 1970-01-01
  • 2011-03-31
  • 1970-01-01
  • 2023-01-04
  • 1970-01-01
  • 2023-03-18
相关资源
最近更新 更多