Вычислить удобочитаемую временную метку из плавающей запятой (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"));