我有一个旧数据格式的DateTime结构,我无法访问任何规范。有一个字段指示数据的日期时间,但它不是我识别的任何格式。它似乎存储为32位整数,每天递增20。有没有人遇到这样的事情?
编辑:
示例:1088631936 DEC = 80 34 E3 40 00 00 00 00 HEX = 09/07/2007
编辑:
首先,抱歉延迟。我原本希望在周末做些什么,但是无法做到。
其次,这种日期格式比我最初的想法更怪异。它似乎是某种指数或对数方法,因为日期不会以递增的速度变化。
第三,我解释这些值的已解散的应用程序只显示日期部分,所以我不知道时间部分是什么。
示例数据: (十六进制值为big-endian,日期为mm / dd / yyyy)
0x40000000 = 01/01/1900
0x40010000 = 01/01/1900
0x40020000 = 01/01/1900
0x40030000 = 01/01/1900
0x40040000 = 01/01/1900
0x40050000 = 01/01/1900
0x40060000 = 01/01/1900
0x40070000 = 01/01/1900
0x40080000 = 01/02/1900
0x40090000 = 01/02/1900
0x400A0000 = 01/02/1900
0x400B0000 = 01/02/1900
0x400C0000 = 01/02/1900
0x400D0000 = 01/02/1900
0x400E0000 = 01/02/1900
0x400F0000 = 01/02/1900
0x40100000 = 01/03/1900
0x40110000 = 01/03/1900
0x40120000 = 01/03/1900
0x40130000 = 01/03/1900
0x40140000 = 01/04/1900
0x40150000 = 01/04/1900
0x40160000 = 01/04/1900
0x40170000 = 01/04/1900
0x40180000 = 01/05/1900
0x40190000 = 01/05/1900
0x401A0000 = 01/05/1900
0x401B0000 = 01/05/1900
0x401C0000 = 01/06/1900
0x401D0000 = 01/06/1900
0x401E0000 = 01/06/1900
0x401F0000 = 01/06/1900
0x40200000 = 01/07/1900
0x40210000 = 01/07/1900
0x40220000 = 01/08/1900
0x40230000 = 01/08/1900
....
0x40800000 = 05/26/1901
0x40810000 = 06/27/1901
0x40820000 = 07/29/1901
....
0x40D00000 = 11/08/1944
0x40D10000 = 08/29/1947
答案 0 :(得分:7)
它不是整数,它是32位浮点数。我还没有完全确定格式,它不是IEEE。
编辑:得到它。 1位符号,11位指数,偏移量为0x3ff,20位尾数,左侧为隐含位。在C中,仅假设正数:
double offset = pow(2, (i >> 20) - 0x3ff) * (((i & 0xfffff) + 0x100000) / (double) 0x100000);
这会产生0x40000000 = 2.0,因此开始日期必须是12/30/1899。
再次编辑:因为你很善意接受我的答案,而你似乎对速度感到担心,我想我会稍微改进一下。您不需要实数的小数部分,因此我们可以仅使用按位运算直接转换为整数。在这次Python中,完成测试结果。我已经包含了一些中间值以提高可读性。除了没有负数的限制之外,当指数超过19时,这个版本可能会有问题,但这应该让你在3335年之前保持良好状态。
>>> def IntFromReal32(i):
exponent = (i >> 20) - 0x3ff
mantissa = (i & 0xfffff) + 0x100000
return mantissa >> (20 - exponent)
>>> testdata = range(0x40000000,0x40240000,0x10000) + range(0x40800000,0x40830000,0x10000) + [1088631936]
>>> from datetime import date,timedelta
>>> for i in testdata:
print "0x%08x" % i, date(1899,12,30) + timedelta(IntFromReal32(i))
0x40000000 1900-01-01
0x40010000 1900-01-01
0x40020000 1900-01-01
0x40030000 1900-01-01
0x40040000 1900-01-01
0x40050000 1900-01-01
0x40060000 1900-01-01
0x40070000 1900-01-01
0x40080000 1900-01-02
0x40090000 1900-01-02
0x400a0000 1900-01-02
0x400b0000 1900-01-02
0x400c0000 1900-01-02
0x400d0000 1900-01-02
0x400e0000 1900-01-02
0x400f0000 1900-01-02
0x40100000 1900-01-03
0x40110000 1900-01-03
0x40120000 1900-01-03
0x40130000 1900-01-03
0x40140000 1900-01-04
0x40150000 1900-01-04
0x40160000 1900-01-04
0x40170000 1900-01-04
0x40180000 1900-01-05
0x40190000 1900-01-05
0x401a0000 1900-01-05
0x401b0000 1900-01-05
0x401c0000 1900-01-06
0x401d0000 1900-01-06
0x401e0000 1900-01-06
0x401f0000 1900-01-06
0x40200000 1900-01-07
0x40210000 1900-01-07
0x40220000 1900-01-08
0x40230000 1900-01-08
0x40800000 1901-05-26
0x40810000 1901-06-27
0x40820000 1901-07-29
0x40e33480 2007-09-07
答案 1 :(得分:3)
您确定这些值对应于09/07/2007吗?
我问,因为1088631936是自Linux(等)零日期以来的秒数:01/01/1970 00:00:00至06/30/2004 21:45:36。
似乎我觉得这个值通常是零日期以来的秒数。
编辑:我知道这很可能不是正确的答案。这只是一种方法(有效方法),但我认为需要更多信息(参见评论)。编辑这个(再次)将问题放在前面,希望其他人回答它或提出想法。我:公平,体育和分享精神:D
答案 2 :(得分:1)
我会说vmarquez很接近。
以下是2009-3-21和2009-3-22的日期,作为unix epochtime:
In [8]: time.strftime("%s", (2009, 3, 21, 1, 1, 0, 0,0,0))
Out[8]: '1237590060'
In [9]: time.strftime("%s", (2009, 3, 22, 1, 1, 0, 0,0,0))
Out[9]: '1237676460'
这里他们是十六进制的:
In [10]: print("%0x %0x" % (1237590060, 1237676460))
49c4202c 49c571ac
如果你只取前5位数,那么增长是21.哪种方式符合你的格式,是吗?
答案 3 :(得分:1)
某些背景会很有用。如果您的数据文件看起来像字面上或者至少是比喻性的,就像这个文件一样,vmarquez就是钱。
http://www.slac.stanford.edu/comp/net/bandwidth-tests/eventanalysis/all_100days_sep04/node1.niit.pk
该引用是由可用带宽估计工具(ABwE)生成的数据 - 奇怪的项目是它实际上包含该1088631936值以及上下文。那个例子
date time abw xtr dbcap avabw avxtr avdbcap rtt timestamp
06/30/04 14:43:48 1.000 0.000 1.100 1.042 0.003 1.095 384.387 1088631828
06/30/04 14:45:36 1.100 0.000 1.100 1.051 0.003 1.096 376.408 1088631936
06/30/04 14:47:23 1.000 0.000 1.100 1.043 0.003 1.097 375.196 1088632043
似乎与建议的21:45:36时间值有7个小时的偏差。 (可能是斯坦福本地,在夏令时上运行。)
答案 4 :(得分:0)
好吧,你只是向我们展示了你的程序如何使用8位数中的2位,所以我们必须假设其他6位被忽略(因为你的程序可以用其他数字做任何想做的事)。
所以,我们可以说输入格式是: 40mn0000 其中m和n是两个十六进制数字。
然后,输出是: 01/01/1900 + floor((2 ^(m + 1)-2)+ n * 2 ^(m-3))天
说明:
使用这两个规则,并使用数字,你可以得到上面的等式。 (除了因为输出不显示小数天而添加的地板除外)。
我想你可以通过用一个2位十六进制数H替换两个单独的十六进制变量m和n来重写这个。但是,我认为这会使方程变得更加丑陋。