Converter data de Delphi para Java  XML
Índice dos Fóruns » Assuntos gerais (Off-topic)
Autor Mensagem
renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline

Alguém já precisou converter data de Delphi para Java?

Bem se não me engano o formato interno das datas em Java é um long de milissegundos desde não sei quando. Já no delphi é um ponto flutuante (double) com a seguinte faixa:

Valor mínimo: -657434.0 (01/01/0100 12:00:00.000 AM)
Valor máximo: 2958465.99999 (31/12/9999 11:59:59.999 PM)

Eu preciso disso porque o banco que acesso com Java é lido e escrito por um alienígena escrito em Delphi.

Já verifiquei e essa faixa cabe no campo do banco de dados, apesar de uma parada sinistra aí. Aliás no MySQL tem uma coisa muito louca: ÀS VEZES ele PERMITE chaves primárias IGUAIS e ÀS VEZES NÃO, sem nenhuma explicação aparente!!! Esse campo de data que é um float no formato do Delphi é que é a chave primária.

De qualquer forma continuarei pesquisando...

This message was edited 1 time. Last update was at 24/02/2005 18:29:54

thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17539
Offline

Quanto o Delphi retorna para a data 1/1/1970 (que para o Java é o tempo 0?) Aí dá para fazer umas contas.



[WWW]
renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline

thingol wrote:Quanto o Delphi retorna para a data 1/1/1970 (que para o Java é o tempo 0?) Aí dá para fazer umas contas.

´

É disso que estou com medo, de fazer as contas!!!
Queria achar algo pronto.

Bem vou ver isso aí e posto depois...
fzampa
Virtual Machine Man
[Avatar]

Membro desde: 05/11/2004 18:22:45
Mensagens: 615
Localização: Belo Horizonte
Offline

Se tivesse guardado no formato Date do banco de dados teria dado esse problema??? Como está guardada a data?

This message was edited 1 time. Last update was at 25/02/2005 00:01:38



[MSN]
renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline

@editado

fzampa wrote:Se tivesse guardado no formato Date do banco de dados teria dado esse problema??? Como está guardada a data?


Aí é que tá, o programa em Delphi armazena a data como um campo float e não como um date que provavelmente o MySQL tem. E não posso mudar esse fato.

Caras por enquanto estou dando uma pesquisada numas coisas, depois posto mais... agora vou almoçar

This message was edited 1 time. Last update was at 25/02/2005 13:31:01

Daniel Quirino Oliveira
Moderador
[Avatar]

Membro desde: 23/03/2003 23:57:34
Mensagens: 3282
Localização: Awawawawa (Araraquara) - SP
Offline

Diquinha quente: http://joda-time.sourceforge.net/

This message was edited 1 time. Last update was at 25/02/2005 13:45:08


Daniel Quirino Oliveira
[Email] [WWW]
renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline

Daniel Quirino Oliveira wrote:Diquinha quente: http://joda-time.sourceforge.net/


Nome esquisito: Joda, mistura de Java com...
O difícil é achar informações, mas estou olhando a documentação...
renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline

Minhas conclusões até agora:

Bem a data e a hora do Delphi ficam num TDateTime, que é um apelido para o tipo Double (8 bytes). Ele armazena o número de dias passados desde 30/12/1899, indo para valores negativos e positivos, observando-se os valores limites já citados. E também pode admitir valores fracionários, de modo que a data 30/12/1899 12h:0min:0s:0ms é representada como 0,5. A parte fracionária então representa as horas, minutos, segundos e milissegundos, ocupando para isso uma faixa de 8 dígitos na base 10, de modo que a data 30/12/1899 23h:59min:59s:999ms é representada por 0,99999999).

Parêntesis: por isso a data máxima limite indicada acima como 31/12/9999 11:59:59.999 na verdade é representada pelo valor 2958465.99999999 e não 2958465.999999, que na verdade representa a data 31/12/9999 11:59:59.136 (136 milissegundos e não 999).

Bem descobri essas coisas olhando o código das funções EncodeDate e EncodeTime, que pegam valores separados de ano/mês/dia e hora/minuto/segundo/milissegundo, respectivamente, e transformam num TDateTime cada uma, bastando somar os dois valores para obter a representação conjunta de data e hora.

Tal representação é como a do Java, só que este usa um inteiro (long) de se não me engano 8 bytes também, que representa os milisegundos desde 1/1/1970 (isso tem a ver com Unix) enquanto que TDateTime representa dias desde 30/12/1899, e de modo fracionário, o que permite também reepresentar os milissegundos.

Bem se eu não achar algo pronto, vou ter que implementar essas funções EncodeDate e EncodeTime em Java, adaptando o algoritmo usado. E também terei que adaptar as funções contrárias, de decodificação, já que fazemos consultas no banco de dados pelo Java. Bem se tiver que fazer isso provavelmente vou usar o GregorianCalendar ou então o Joda-time que o Quirino indicou. Aliás procurei e não achei nada na documentação dessa ferramenta sobre converter para esse formato do Delphi ou qualquer outro. Mas minha impressão é que ela é uma boa biblioteca para trabalhar. Bem, ela diz que a API de datas do Java é lenta e ineficiente.

PS: no meu micro o long zero é retornado pela classe java.util.Date como 31/12/1969 21h, ou seja três horas antes que o normal. Meu SO é Windows e o fuso horário é GMT -3h. Muito estranho isso, espero descobrir o que está acontecendo.

Bem vou continuar nessa labuta e continuo aceitando sugestões.

This message was edited 1 time. Last update was at 25/02/2005 19:12:36

renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline

Bem acho que com o que descobri agora já dá pra fazer o que eu quero!!

renato3110 wrote:Parêntesis: por isso a data máxima limite indicada acima como 31/12/9999 11:59:59.999 na verdade é representada pelo valor 2958465.99999999 e não 2958465.999999, que na verdade representa a data 31/12/9999 11:59:59.136 (136 milissegundos e não 999).


Na verdade 2958465.99999999 ainda é um valor aproximado, arredondado em milissegundos. Isto explica as frações abaixo ou acima do valor original na operação contrária. Tais frações devem ser arredondadas para corrigir a aproximação inicial.

renato3110 wrote:PS: no meu micro o long zero é retornado pela classe java.util.Date como 31/12/1969 21h, ou seja três horas antes que o normal. Meu SO é Windows e o fuso horário é GMT -3h. Muito estranho isso, espero descobrir o que está acontecendo.


Bem quanto à isso o que acontece é que ao formatar a data eu obtenho o valor para o meu fuso horário (-3h) automaticamente. A data 1/1/1970 0h é referente ao GMT 00:00. Na verdade não compreendo qual era a minha dúvida quanto à isso!!!

renato3110 wrote:Aliás no MySQL tem uma coisa muito louca: ÀS VEZES ele PERMITE chaves primárias IGUAIS e ÀS VEZES NÃO, sem nenhuma explicação aparente!!!


Bem anida queria saber isso!! Alguém tem uma luz????

Conversão de datas

Bem, o principal formato de data no Delphi é o utilizado pelo TDateTime, relacionado à "automação OLE" e com as seguntes características:

- Valor zero: 30/12/1899 0h GMT 00:00
- Armazenado em dias fracionados (precisão de milissegundos)
- Limites: -657434.0 (01/01/0100 12h), 2958465.9999999 (31/12/9999 23:59:59.999) (Bem na verdade acho que dá pra ultrapassar estes valores sem problemas no Delphi, parece que o limite refere-se apenas à especificação)

No java, a classe java.util.Date armazena a data no padrão UTC usado pelo Unix, com as seguintes características:

- Valor zero: 1/1/1970 0h GMT 00:00
- Armazenado em milissegundos inteiros
- Limites: São milhões de anos em ambos os sentidos, algo assim

Transformação Mágica

Bem após queimar o tico e o teco cheguei na feliz conclusão que são necessárias apenas duas linhas para fazer a conversão, uma para a conversão de Java para Delphi e outra para a conversão contrária. Para tal devemos considerar os dias passados entre os respectivos zeros, 30/12/1899 e 1/1/1970. São 25569 dias, seguindo o calendário gregoriano. Devemos considerar também os milissegundos existentes em um dia, 24 * 60 * 60 * 1000 = 86400000. As fórmulas ficam assim (onde Delphi é um double que representa os dias TDateTime e Java um long que representa os milissegundos UTC):




Exemplo de conversão para a data 1/1/1970 23:59:59.999 GMT 00:00:


Bom ainda falta implementar isso mas fiquei muito contente quando meus neurônios me contaram que seria apenas uma linha para cada conversão
Dharis
JavaBaby
[Avatar]

Membro desde: 12/11/2003 16:06:56
Mensagens: 99
Localização: Rio Branco, Acre
Offline

renato3110 wrote:Aliás no MySQL tem uma coisa muito louca: ÀS VEZES ele PERMITE chaves primárias IGUAIS e ÀS VEZES NÃO, sem nenhuma explicação aparente!!! Esse campo de data que é um float no formato do Delphi é que é a chave primária

O MySQL não permite chaves primárias iguais.
A questão é saber se os valores de pontos flutuantes são exatamente iguais, erros de precisão podem ocorrer.
Se você ver em Comparing floating point numbers, comparações == entre valores de pontos flutuantes podem ser falsas, mesmo você acreditando que os números são os mesmos.

Dharis
renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline

Dharis, usei o MySQL-Front e cadastrei manualmente no banco, copiei o valor 38411,9890920833 e consegui criar um novo registro, mas tem hora que não dá!!!!
renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline


renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline

Uma dúvida: quando eu converto um double para long no método javaDate acima, ele arredonda o valor ou trunca? Exemplo:

double 1,5 trunca para 1 ou arredonda para 1 ou 2?
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17539
Offline

O "cast" de double para long trunca (para baixo, se for um número positivo, e para cima, se for um número negativo.)

(long) 1.3 -> 1
(long) 1.5 -> 1
(long) 1.51 -> 1
(long) -1.3 -> -1
(long) -1.5 -> -1
(long) -1.51 -> -1

Eu digo que é "para cima", no caso de números negativos, porque -1.5 é menor que -1.



[WWW]
renatosilva
GUJ Master

Membro desde: 16/12/2004 17:09:19
Mensagens: 1787
Offline

Sacado, então tem como usar uma função de arredondamento? Porque as fórmulas não podem truncar, elas têm que arredondar!
 
Índice dos Fóruns » Assuntos gerais (Off-topic)
Ir para:   
Powered by JForum 2.1.8 © JForum Team