Reputation: 1583
I have a server-equipment configuration where I need to change the equip date config, using UDP. The server is written in Java and the equipment, in Delphi.
So, the flow of the data is this:
Java server (Java date) -> UDP (integer date) -> Delphi equipment (Delphi date)
The problem is that when I pass the date as an integer, java calculates miliseconds from 1970, and Delphi, seconds. I pass then the date as following: today.getTime() / 1000
, but the equipment understands this as a 2008 date, when we're on 2012.
I can change the Java code, but the equipment is 3rd party and I don't have access to it's source code.
There's difference between Java and Delphi date parsing that allow this discrepancy?
EDIT: Thanks to MДΓΓ БДLL I noticed I was multiplying by 1000 instead of dividing by it, I now have a better date, but still wrong (was somewhen in 2033, now it's in 2008).
Upvotes: 6
Views: 3946
Reputation: 595981
Delphi's DateUtils
unit has UnixToDateTime()
and DateTimeToUnix()
functions for converting between TDateTime
and Unix timestamps, which are expressed as seconds from the Unix epoch (Jan 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's Date
class, on the other hand, is based on milliseconds from the Unix epoch instead. That is easy to take into account, though:
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;
Alternatively:
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;
Either way:
// 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;
Upvotes: 6
Reputation: 9096
Get the JSON superobect package from www.progdigy.com and extract the functions JavaToDelphiDateTime and v.v. from the source files.
Updated 3 Mar 2014:
Progdigy.com no longer serves these files. Get the files from Google. The official 1.2.4 ZIP file in the download section http://code.google.com/p/superobject/downloads/list dates from 2010, but the individual files in http://code.google.com/p/superobject/source/browse have updates up until Oct 2012.
You must use those updated files because there was an obscure error in datetime conversions happening around the switch to daylight savings time in leapyears.
Upvotes: 1
Reputation: 989
As far I know Java date is based on UTC so you also have to convert local time from/to UTC. These functions use milliseconds, adapt the code to your needs.
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;
Upvotes: 3
Reputation: 125669
A Unix time stamp is the same as the one used in Java. Delphi's TDateTime, on the other hand, is based on a starting date of 12:01 AM on 12/30/1899 (it's a COM compatibility thing), so some conversion is necessary. These functions will do it; I've also added a quick piece of test code to show the conversion works correctly both ways.
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;
Upvotes: 5