2009-03-20 19 views
6

Tengo la estructura DateTime para un formato de datos antiguo al que no tengo acceso a ninguna especificación. Hay un campo que indica la fecha y hora de los datos, pero no está en ningún formato que reconozca. Parece estar almacenado como un entero de 32 bits, que se incrementa en 20 por día. ¿Alguien ha encontrado algo como esto?¿Qué formato de fecha y hora es este?

EDIT:

Ejemplo: 1088631936 Dec = 80 34 E3 40 00 00 00 00 HEX = 09/07/2007

EDIT:

En primer lugar, lo siento por el retraso. Esperaba hacer cosas durante el fin de semana, pero no pude.

En segundo lugar, este formato de fecha es más raro de lo que pensé inicialmente. Parece ser una especie de método exponencial o logarítmico, ya que las fechas no cambian a un ritmo creciente.

En tercer lugar, la aplicación obsoleta que tengo para interpretar estos valores solo muestra la parte de fecha, por lo que no sé cuál es la porción de tiempo.

Ejemplo datos: (valores hexadecimales son grandes-endian, fechas son mm/dd/aaaa)

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 = 04/01/1900
0x40150000 = 04/01/1900
0x40160000 = 04/01/1900
0x40170000 = 04/01/1900
0x40180000 = 05/01/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 = 26/05/1901
0x40810000 = 06/27/1901
0x40820000 = 07/29/1901
....
0x40D00000 = 11/08/1944
0x40D10000 = 08/29/1947

EDIT: finalmente me di cuenta de esto, pero ya que ya he renunciado a los puntos por la recompensa, voy a retrasar la solución en caso de que alguien quiera darle una oportunidad.

Por cierto, no hay ningún componente de tiempo para esto, es puramente para almacenar fechas.

+0

¿Sabes * cualquier cosa * sobre el formato de datos, como el nombre de un programa asociado? –

+0

O tal vez incluya un ejemplo? –

+0

Lo siento, su ejemplo no tiene ningún sentido para mí. ¿A qué te refieres con "DEC =" y "OCT =" y por qué "igualan" diferentes tipos? –

Respuesta

7

No es un entero, es un número de coma flotante de 32 bits. Todavía no he resuelto el formato, no es IEEE.

Editar: lo tengo.Signo de 1 bit, exponente de 11 bits con un desplazamiento de 0x3ff, y mantisa de 20 bits con un bit implícito a la izquierda. En C, suponiendo que los números positivos solamente:

double offset = pow(2, (i >> 20) - 0x3ff) * (((i & 0xfffff) + 0x100000)/(double) 0x100000); 

Esto produce 0x40000000 = 2,0, por lo que la fecha de partida debe ser 12/30/1899.

Editar nuevamente: ya que tuvo la amabilidad de aceptar mi respuesta, y parece preocupado por la velocidad, pensé que iba a refinar esto un poco. No necesita la parte fraccional del número real, por lo que podemos convertir directamente a entero utilizando solo operaciones a nivel de bit. En Python esta vez, complete con los resultados de la prueba. He incluido algunos valores intermedios para una mejor legibilidad. Además de la restricción de números negativos, esta versión puede tener problemas cuando el exponente pasa de 19, pero esto debería mantenerte hasta el año 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 
+0

¿Eso no daría 0x40220000 -> 01/06/1900? – mbeckish

+0

No, es correcto. 0x40220000 = 9.0, agregue al 30/12/1899 el 12/39/1899; restar 31 días y llevar el mes, te deja el 1/08/1900. –

+0

Bien hecho. Su respuesta no es solo correcta, es considerablemente más rápida que la forma en que lo hice. Ten una recompensa – Kevin

3

¿Estás seguro de que los valores corresponden a 07/09/2007?

Lo pregunto porque 1088631936 es el número de segundos desde Linux (et al) fecha cero: 01/01/1970 00:00:00 a 30/06/2004 21:45:36.

Me parece razonable pensar el valor son segundos desde esta fecha habitual cero.

Editar: Sé que es muy posible que esto no sea la respuesta correcta. Es solo un enfoque (uno válido) pero creo que se necesita más información (ver los comentarios). Editando esto (otra vez) para llevar la pregunta al frente con la esperanza de que alguien más la responda o brinde ideas. Me: con una imparcialidad, deportivo y espíritu de compartir: D

1

diría que vmarquez está cerca.

Estas son las fechas y 2009-3-21 03/22/2009 como 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' 

Y aquí están en hexadecimal:

In [10]: print("%0x %0x" % (1237590060, 1237676460)) 
49c4202c 49c571ac 

Si toman sólo los primeros 5 dígitos , el crecimiento es 21. ¿Qué coincide con tu formato, neg?

+0

Gracias Pasi. Las matemáticas son simples, limpias y muy cercanas a la descripción. Me hace preguntarme si el "incremento de 20 por día" es exacto o se parece más a "como 20 por día". De todos modos, nos queda el problema de la época (¿qué es la fecha cero?). – vmarquez

1

Algún contexto sería útil. Si su archivo de datos tiene un aspecto literal, o al menos figurado, como este archivo, vmarquez está en el dinero.

http://www.slac.stanford.edu/comp/net/bandwidth-tests/eventanalysis/all_100days_sep04/node1.niit.pk

Esa referencia es producida por los datos Disponible herramienta de ancho de banda de estimación (abwe) - el elemento curioso es que en realidad contiene el valor que 1088631936, así como el contexto. Ese ejemplo


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 
parece tener un desplazamiento de siete horas desde el valor de tiempo sugerido de 21:45:36. (Probablemente Stanford local, funcionando en Horario de verano).

+0

¡Eso es un gran hallazgo! +1 – vmarquez

0

Bueno, solo nos has mostrado cómo tu programa usa 2 de los 8 dígitos, así que tendremos que asumir que los otros 6 son ignorados (porque tu programa podría estar haciendo lo que quiera con esos otros dígitos).

Por lo tanto, podríamos decir que el formato de entrada es: 40mn0000 donde m y n tienen dos dígitos hexadecimales.

Entonces, la salida es: 01/01/1900 + piso ((2^(m + 1) -2) + n * 2^(M-3)) días

Explicación:

  1. En cada ejemplo, observe que incrementar n en 1 aumenta el número de días en 2^(m-3).
  2. Observe que cada vez que n va de F a 0, m se incrementa.

Usando estas dos reglas, y jugando con los números, obtienes la ecuación anterior. (Excepto por piso, que se agregó porque la salida no muestra días fraccionarios).

Supongo que podría reescribir esto reemplazando las dos variables hexadecimales separadas myn con un solo número hexadecimal de 2 dígitos H. Sin embargo, creo que eso haría la ecuación mucho más fea.

+0

Felicidades mbeckish. Confirmó su fórmula. – vmarquez

+0

te perdiste el primer ejemplo que di: 0x40E33480 = 09/07/2007 – Kevin

Cuestiones relacionadas