Какой формат даты и времени это? - PullRequest
6 голосов
/ 21 марта 2009

У меня есть структура DateTime для старого формата данных, для которого у меня нет доступа к каким-либо спецификациям. Есть поле, которое указывает дату и время данных, но оно не в каком-либо формате, который я распознаю. Кажется, он хранится как 32-разрядное целое число, которое увеличивается на 20 для каждого дня. Кто-нибудь когда-нибудь сталкивался с чем-то подобным?

EDIT:

Пример: 1088631936 DEC = 80 34 E3 40 00 00 00 00 HEX = 09/07/2007

EDIT:

Прежде всего, извините за задержку. Я надеялся сделать что-нибудь в выходные, но не смог.

Во-вторых, этот формат даты более странный, чем я думал. Похоже, что это какой-то экспоненциальный или логарифмический метод, поскольку даты не меняются с возрастающей скоростью.

В-третьих, несуществующее приложение, которое у меня есть для интерпретации этих значений, показывает только часть даты, поэтому я не знаю, какая часть времени.

Пример данных: (Шестнадцатеричные значения имеют порядковый номер, даты указаны в мм / дд / гггг)

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 = 29/29/1901
....
0x40D00000 = 11/08/1944
0x40D10000 = 29.09.1947

РЕДАКТИРОВАТЬ: Я наконец понял это, но так как я уже отдал очки за награду, я буду задерживать решение в случае, если кто-то захочет дать ему шанс.

Кстати, для этого нет компонента времени, он предназначен только для хранения дат.

Ответы [ 5 ]

7 голосов
/ 25 марта 2009

Это не целое число, это 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
3 голосов
/ 21 марта 2009

Вы уверены, что значения соответствуют 09/07/2007?

Я спрашиваю, потому что 1088631936 - это количество секунд с нулевой даты в Linux (и др.): С 01.01.1970 с 00:00:00 по 30.06.2004 21: 45: 36.

Мне кажется разумным думать, что значение равно секундам с этой обычной нулевой даты.

Редактировать: я знаю, что очень возможно, что это не будет правильным ответом. Это только один подход (действительный), но я думаю, что нужно больше информации (см. Комментарии). Редактирование этого (снова), чтобы вывести вопрос на передний план в надежде, что кто-то еще ответит на него или подаст идеи. Я: со справедливостью, спортивным и разделяющим духом: D

1 голос
/ 22 марта 2009

Некоторый контекст был бы полезен. Если ваш файл данных выглядит буквально или, по крайней мере, в переносном смысле, как этот файл, 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. (Вероятно, местный Стэнфорд, работает на летнее время.)
1 голос
/ 21 марта 2009

Я бы сказал, что Вмаркес близко.

Вот даты 2009-3-21 и 2009-3-22 как эпоха unix:

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. Какой тип соответствует вашему формату, neg?

0 голосов
/ 25 марта 2009

Ну, вы только показали нам, как ваша программа использует 2 из 8 цифр, поэтому мы должны предположить, что остальные 6 игнорируются (потому что ваша программа может делать все что угодно с этими другими цифрами).

Итак, мы можем сказать, что формат ввода: 40mn0000 где m и n - две шестнадцатеричные цифры.

Тогда вывод: 01/01/1900 + этаж ((2 ^ (m + 1) -2) + n * 2 ^ (m-3)) дней

Пояснение:

  1. В каждом примере обратите внимание, что увеличение n на 1 увеличивает количество дней на 2 ^ (м-3).
  2. Обратите внимание, что каждый раз, когда n переходит от F к 0, m увеличивается.

Используя эти два правила и играя с числами, вы получите уравнение выше. (За исключением пола, который был добавлен, потому что выходные данные не отображают дробные дни).

Полагаю, вы могли бы переписать это, заменив две отдельные шестнадцатеричные переменные m и n одним двузначным шестнадцатеричным числом H. Однако я думаю, что это сделало бы уравнение намного более уродливым.

...