Вычислить удобочитаемую временную метку из плавающей запятой (EasyIP)?

Мне нужно преобразовать некоторые метки даты + времени в данные XML, извлеченные из Easy-IP. Я не распознаю необработанные значения, они кажутся значениями с плавающей запятой, но целая часть числа слишком мала для стиля UNIX.

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

Я считаю, что внутренней базой данных является Firebird, но, согласно их документации, они начинают считать с 1 января 1753 года.

Некоторые выборочные значения (каждая строка представляет собой отдельную сущность), которые должны относиться к действиям, которые произошли за последние 15 лет, и, вероятно, гораздо более поздним:

CREATED="39660.2632087847" UPDATED="39660.2632160185"
CREATED="39660.2631284838" UPDATED="39750.4032429514"
FIRST_SUCCESSFUL_CONTACT="39668.128960544"  LAST_SUCCESSFUL_CONTACT="41301.0505147685"
FIRST_SUCCESSFUL_CONTACT="39668.1289603588" LAST_SUCCESSFUL_CONTACT="41301.0505142245"

Я надеюсь, что кто-то еще уже видел это раньше, и не ставить загадку. Бонусные баллы, если у вас есть надежный способ конвертировать в дату и время, используя XSL, Java или (менее предпочтительный) PERL.

2 ответа

Решение

Я предполагаю, что значения взяты из внутреннего представления Delphi TDateTime:

Delphi-программы внутренне представляют значения TDateTime в виде значения с плавающей запятой, неотъемлемая часть представляет количество дней с 30 декабря 1899 года, а дробная часть - это доля дня с полуночи.

Так, например,

  • 39660 является Jul-31-2008
  • 0.2632087847 является 6:19:01.239 AM

Итак, ваш первый пример 2008-07-31 06:19:01

Я не думаю, что данные являются внутренним представлением Firebird дат, поэтому я думаю, что оригинальная система не использовала TimeStamp тип данных, но с двойной точностью или другой числовой тип для хранения дат.

С учетом всего вышесказанного, похоже, что самый простой способ преобразования дат - это написать программу на Delphi для изменения представления даты. Например, чтобы вычислить показанные даты, я написал:

procedure TForm1.Button1Click(Sender: TObject);
var
  Dt: TDateTime;
begin
  Dt := 39660.2632087847;
  ShowMessage(FormatDateTime('dd/mm/yyyy hh:nn:ss.zzz', Dt));
end;

Если у вас нет Delphi под рукой, есть другие инструменты, которые используют аналогичные представления, и теперь у вас есть вся информация, чтобы самостоятельно выполнять математику, если вам не повезло. Преобразование в UnixTime не особенно сложно.

Я не смог найти точный пример этого преобразования для Java. Вот упрощенная версия того, что я буду использовать:

public static String convertEasyIPTime (double dateTimeDouble, String timeZoneCode) {

  TimeZone tz = TimeZone.getTimeZone(timeZoneCode);

  long days = (long) dateTimeDouble;
  long adjustedDays = days - 25569; // Days between Jan 1st 1753 (Delphi) and Dec 31st 1970 (Java)

  long datePortion = adjustedDays * 24 * 60 * 60 * 1000;
  long timePortion =  (long) ((dateTimeDouble - days) * 60 * 60 * 24 * 1000);

  int zoneAndDSTOffset = tz.getOffset(datePortion);

  Date output = new Date (datePortion + timePortion - zoneAndDSTOffset);
  DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");  
  formatter.setTimeZone(TimeZone.getTimeZone(timeZoneCode)); 
  return formatter.format(output);
}

Пример вызова этого:

System.out.println(convertEasyIPTime (39940.1295844213d, "CST"));
Другие вопросы по тегам