Конвертировать дату в Java в целое число, а затем в Delphi Time - PullRequest
6 голосов
/ 03 января 2012

У меня есть конфигурация серверного оборудования, где мне нужно изменить конфигурацию даты экипировки, используя UDP. Сервер написан на Java и оборудование, на Delphi.

Итак, поток данных таков:

Java server (Java date) -> UDP (integer date) -> Delphi equipment (Delphi date)

Проблема в том, что когда я передаю дату как целое число, java вычисляет милисекунды с 1970 года, а Delphi - секунды. Затем я передаю следующую дату: today.getTime() / 1000, но оборудование понимает ее как дату 2008 года, когда мы находимся в 2012 году.

Я могу изменить код Java, но оборудование стороннего производителя, и у меня нет доступа к его исходному коду.

Есть ли разница между синтаксическим анализом даты в Java и Delphi, которая допускает это расхождение?

EDIT: Благодаря MДГ БДLL я заметил, что я умножаю на 1000 вместо деления на нее, теперь у меня есть лучшая дата, но все же неправильно (когда-то в 2033 году, сейчас в 2008).

Ответы [ 4 ]

6 голосов
/ 04 января 2012

Delphi's DateUtils имеет функции UnixToDateTime() и DateTimeToUnix() для преобразования между TDateTime и метками времени Unix, которые выражаются в секундах от эпохи Unix (1 января 1970 00:00: 00 GMT):

// 1325606144 = Jan 3 2012 3:55:44 PM GMT

uses
  DateUtils;

var
  DT: TDateTime;
  Unix: Int64;
begin
  DT := UnixToDateTime(1325606144);
  // returns Jan 3 2012 3:55:44 PM

  Unix := DateTimeToUnix(EncodeDate(2012, 1, 3) + EncodeTime(15, 55, 44, 0));
  // returns 1325606144
end;

Класс Java Date, с другой стороны, основан на миллисекундах с эпохи Unix . Это легко принять во внимание, хотя:

uses
  DateUtils;

function JavaToDateTime(Value: Int64): TDateTime;
begin
  Result := UnixToDateTime(Value div 1000);
end;

function DateTimeToJava(const Value: TDateTime): Int64;
begin
  Result := DateTimeToUnix(Value) * 1000;
end;

В качестве альтернативы:

uses
  SysUtils, DateUtils;

// UnixDateDelta is defined in SysUtils...

function JavaToDateTime(Value: Int64): TDateTime;
begin
  Result := IncMilliSecond(UnixDateDelta, Value);
 end;

function DateTimeToJava(const Value: TDateTime): Int64;
begin
  Result := MilliSecondsBetween(UnixDateDelta, Value);
  if Value < UnixDateDelta then
    Result := -Result;
end;

В любом случае:

// 1325606144000 = Jan 3 2012 3:55:44 PM GMT

var
  DT: TDateTime;
  Java: Int64;
begin
  DT := JavaToDateTime(1325606144000);
  // returns Jan 3 2012 3:55:44 PM

  Java := DateTimeToJava(EncodeDate(2012, 1, 3) + EncodeTime(15, 55, 44, 0));
  // returns 1325606144000
end;
5 голосов
/ 03 января 2012

Метка времени Unix такая же, как и в Java. TDateTime в Delphi, с другой стороны, основан на дате начала работы в 01:01 30.12.1999 (это совместимость с COM), поэтому необходимо некоторое преобразование. Эти функции сделают это; Я также добавил небольшой фрагмент тестового кода, чтобы показать, что преобразование работает правильно в обоих направлениях.

const
  UnixStartDate = 25569.0;

function DateTimeToUnixTime(const ADateTime: TDateTime): Cardinal;
begin
  Result := Round(ADateTime - UnixStartDate) * 86400;
end;

function UnixTimeToDateTime(const UnixDate: Cardinal): TDateTime;
begin
  Result := UnixDate / 86400 + UnixStartDate;
end;

procedure TForm1.Button1Click(Sender: TObject);
var  StartDate: TDateTime;
  UnixDate: Cardinal;
begin
  StartDate := Date();
  Memo1.Lines.Add('Start Date: ' + DateToStr(StartDate));
  UnixDate := DateTimeToUnixTime(StartDate);
  Memo1.Lines.Add('DateTimeToUnixTime = ' + IntToStr(UnixDate));
  Memo1.Lines.Add('UnixTimeToDateTime = ' + DateToStr(UnixTimeToDateTime(UnixDate)));
end;
3 голосов
/ 04 января 2012

Насколько я знаю, дата в Java основана на UTC, поэтому вам также необходимо преобразовать местное время из / в UTC. Эти функции используют миллисекунды, адаптируют код к вашим потребностям.

function TzSpecificLocalTimeToSystemTime(
  lpTimeZoneInformation: PTimeZoneInformation;
  lpLocalTime, lpUniversalTime: PSystemTime): BOOL; stdcall; external 'kernel32.dll';

function SystemTimeToTzSpecificLocalTime(
  lpTimeZoneInformation: PTimeZoneInformation;
  lpUniversalTime, lpLocalTime: PSystemTime): BOOL; stdcall; external 'kernel32.dll';

function JavaToDelphiDateTime(const dt: int64): TDateTime;
var
  t: TSystemTime;
begin
  DateTimeToSystemTime(25569 + (dt / 86400000), t);
  SystemTimeToTzSpecificLocalTime(nil, @t, @t);
  Result := SystemTimeToDateTime(t);
end;

function DelphiToJavaDateTime(const dt: TDateTime): int64;
var
  t: TSystemTime;
begin
  DateTimeToSystemTime(dt, t);
  TzSpecificLocalTimeToSystemTime(nil, @t, @t);
  Result := Round((SystemTimeToDateTime(t) - 25569) * 86400000)
end;
1 голос
/ 04 января 2012

Получите суперобъект JSON с сайта www.progdigy.com и извлеките функции JavaToDelphiDateTime и v.v. из исходных файлов.

Обновлено 3 марта 2014 года:

Progdigy.com больше не обслуживает эти файлы. Получите файлы от Google. Официальный ZIP-файл 1.2.4 в разделе загрузок http://code.google.com/p/superobject/downloads/list датируется 2010 годом, но отдельные файлы в http://code.google.com/p/superobject/source/browse имеют обновления до октября 2012 года.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...