2012-01-03 15 views
6

Tengo una configuración de equipo de servidor donde necesito cambiar la configuración de fecha de equipamiento, usando UDP. El servidor está escrito en Java y el equipo, en Delphi.Fecha de conversión en Java a entero y luego a Delphi Time

Así, el flujo de los datos es la siguiente:

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

El problema es que cuando paso de la fecha como un entero, java calcula milisegundos desde 1970, y Delphi, segundo. Paso la fecha como sigue: today.getTime()/1000, pero el equipo entiende esto como una fecha de 2008, cuando estamos en 2012.

Puedo cambiar el código de Java, pero el equipo es de terceros y no tengo acceso a su código fuente

¿Hay diferencia entre el análisis de fechas de Delphi y Java que permite esta discrepancia?

EDIT: Gracias a MДΓΓ БДLL Noté que estaba multiplicando por 1,000 en lugar de dividir por ella, ahora tengo una fecha mejor, pero sigue siendo incorrecto (en algún tiempo fue en el 2033, ahora es en 2008).

+4

No entiendo completamente. Tienes que pasar de milisegundos desde 1970 a segundos (¿desde 1970?) Pero estás multiplicando por 1000? Milisegundos => segundos significa _divide_ por 1000. –

+3

No conozco ningún tipo de fecha en Delphi que sea segundos desde 1970. ¿Estás seguro de que esta es una pregunta de Delphi? –

+0

Doh! De hecho, estaba multiplicando en lugar de dividir ... pero todavía no solucionó el problema, vea la edición –

Respuesta

4

Una marca de tiempo Unix es la misma que la utilizada en Java. Por otro lado, TDateTime de Delphi se basa en una fecha de inicio de 12:01 am el 30/12/1899 (es una cuestión de compatibilidad COM), por lo que es necesaria cierta conversión. Estas funciones lo harán; También agregué un fragmento rápido de código de prueba para mostrar que la conversión funciona correctamente en ambos sentidos.

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; 
+0

Para todos los no coloniales (? Creo que los británicos son responsables de ese formato?) Que no tienen idea de qué' 12: 01 AM' es .. es '0: 01' NO' 12: 01';) – Voo

+0

Es '0001' o' 0: 01' para las personas que usan 24 horas de tiempo; en formato de 12 horas (AM/PM) es '12:01 AM' como dije. :) –

+0

Sí, solo quería que suene un poco más divertido;) Pero como alguien que creció con el sistema de 24 horas yo mismo pensé que merecía una mención ya que no creería cuántas personas (al menos en Alemania/Austria)) intuitivamente interpretaría '12:01 AM' como' 12: 01' - o se perdería por qué exactamente cualquier valor mayor a '12: 00' está permitido en un sistema de tiempo de 12 horas para empezar. – Voo

6

unidad de Delphi DateUtils tiene UnixToDateTime() y DateTimeToUnix() funciones para la conversión entre TDateTime y Unix marcas de tiempo, que se expresan como segundos desde la época Unix (ene 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; 

La clase de Java Date, por otro lado, se basa en milisegundos de la época Unix en su lugar. Eso es fácil de tener en cuenta, sin embargo:

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; 

alternativa:

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; 

De cualquier manera:

// 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; 
+0

Esto no funcionó para mí. La función devolvió valores de TDateTime del año 43,000. – TomC

+0

Entonces no lo estaba usando correctamente. –

+0

Siéntase libre de informarme sobre el uso correcto en lugar de decir que lo estaba usando incorrectamente. Tuve éxito utilizando la función JavaToDelphiDateTime del paquete SuperObject que utiliza Delphi-OOP. – TomC

3

Por lo que sé la fecha de Java se basa en UTC lo que también tienen para convertir la hora local desde/a UTC. Estas funciones usan milisegundos, adapte el código a sus necesidades.

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

Obtener el paquete superobect JSON de www.progdigy.com y extraer el JavaToDelphiDateTime funciones y V.V. de los archivos de origen.

Actualizado hace 3 Mar 2014:

Progdigy.com ya no sirve a estos archivos. Obtenga los archivos de Google. El archivo ZIP oficial 1.2.4 en la sección de descarga http://code.google.com/p/superobject/downloads/list data de 2010, pero los archivos individuales en http://code.google.com/p/superobject/source/browse tienen actualizaciones hasta octubre de 2012.

Usted debe usar esos archivos actualizados porque hubo un oscuro error en las conversiones de fecha y hora que ocurren alrededor del cambio al horario de verano en leapyears.

Cuestiones relacionadas