Erro calculando datas com GregorianCalendar no Windows 2000

4 respostas
1112

Pessoal, no sistema aqui da empresa existe um método que calcula datas com GregorianCalendar. Nós já havíamos testado, usado JUnit para testes automáticos, e tudo havia funcionado perfeitamente.

Já há algum tempo, o sistema foi implantado em um cliente, e lá ocorreu um problema de travamento que, debugando, descobrimos que ocorria justamente em nossa classe que calculava datas. Em um método que testava se um dia era ou não feriado, ocorria uma soma de 1 dia em uma data e essa soma não ocorria. Ou seja, ele tentava somar 1 dia a 19/02/2005 e retornava 19/02/2005. Testamos aqui em nossas máquinas e o erro não ocorreu. Criamos um programa pequeno apenas com a classe para testar e o problema mais uma vez ocorreu apenas nas máquinas do cliente, não nas nossas.

O método usa o esquema de milissegundos para calcular a data. Eu fiz um teste usando o método add() do GregorianCalendar, testei na minha máquina e deu certo. Testei em uma máquina que pegamos emprestada do cliente e deu errado.

O programa que usei para testar segue abaixo:

package testeData;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.GregorianCalendar;

/**
 * <B> DoomData </B>
 * 
 * @author wilerson
 * @version 07/01/2005
 */
public class DoomData {

   public static void main( String[] args ) {
      File arq1 = new File( "arq1.txt" );
      File arq2 = new File( "arq2.txt" );
      try {
         arq1.createNewFile();
         arq2.createNewFile();
         BufferedWriter writer = new BufferedWriter( new FileWriter( arq1 ) );
         for ( int i = 1; i < 370; i++ ) {
            writer.write( calcula2( "01/01/2005", i ) + "\r\n" );
         }
         writer.close();
         writer = null;
         writer = new BufferedWriter( new FileWriter( arq2 ) );
         String sdata = "01/01/2005";
         for( int i = 1; i < 370; i++ ) {
            sdata = calcula2( sdata, 1 );
            writer.write( sdata + "\r\n" );
         }
         writer.close();
      }
      catch( IOException e ) {
         e.printStackTrace();
      }
   }
   
   public static String calcula2( String sdata1, int idias ) {
      GregorianCalendar gc = new GregorianCalendar( Integer.parseInt( sdata1.substring( 6, sdata1.length() ).trim().replace( ' ', '0' ) ),
               Integer.parseInt( sdata1.substring( 3, 5 ).trim().replace( ' ', '0' ) ) - 1,
               Integer.parseInt( sdata1.substring( 0, 2 ).trim().replace( ' ', '0' ) ) );

      gc.add( GregorianCalendar.DAY_OF_MONTH, idias );
      String sdataFormat = "";
      String sdia = gc.get( GregorianCalendar.DAY_OF_MONTH ) < 10 ? 
                          "0" + String.valueOf( gc.get( GregorianCalendar.DAY_OF_MONTH ) ) : 
                          String.valueOf( gc.get( GregorianCalendar.DAY_OF_MONTH ) );
      String smes = gc.get( GregorianCalendar.MONTH ) + 1 < 10 ? 
                           "0" + String.valueOf( gc.get( GregorianCalendar.MONTH ) + 1 ) :
                           String.valueOf( gc.get( GregorianCalendar.MONTH ) + 1 );
      String sano = String.valueOf( gc.get( GregorianCalendar.YEAR ) );
      sdataFormat = sdia + "/" + smes + "/" + sano;
      
      return sdataFormat;
   }
}

Reparem que é bem simples, eu o fiz em uns dez minutos só para testar. Na máquina do cliente, ele gerou o arq1.txt corretamente (somando 1 em 1 até 05/01/2006), mas no arq2.txt ele parou de somar a partir de 08/10/2005. Ou seja, ele somou normalmente até 07/10/2005, mas a partir de 08/10/2005, passou a repetir essa data.

Existe algum bug conhecido na GregorianCalendar que poderia gerar um comportamento desse tipo?

A propósito, a máquina do cliente tem as seguintes características:
Intel Celeron 2.0 GHZ
256 MB RAM
Windows 2000 5.00.2195 Service Pack 4

E a versão da J2RE, tanto nas máquinas daqui quanto nas do cliente, é J2RE 1.4.2_04-b05 .

Se puderem me ajudar, obrigado. :¬)

4 Respostas

T

Aham - parece que a mudança para horário de verão (pelo menos para a JVM instalada na máquina desse cliente) vai ser nesse dia.

Já tive um problema com 10/10/2004 em algumas versões da JVM, então isso tem cheiro de horário de verão.

Só pra dar mais uma checada, veja como está o Regional Settings (Portuguese/Brazil?) e o timezone do Windows (se está setado ou não para daylight saving changes), pode ser que estejam diferentes de uma máquina para a outra, por isso é que você não está conseguindo reproduzir o problema.

Para resolver o problema, some sempre 1 dia e 1 hora.

1112

Obrigado, Thingol. Mas eu não consigo entender porque deu problema em 19/02/2005. Mas eu vou fazer a verificação e o teste na segunda.

EDIT: Ah, perdão. Esqueci de pensar no óbvio: horário de verão terminando em 19/02.

1112

Update: Testei e funcionou. Obrigado, Thingol.

T

Não há de quê. Como já tive um problema parecido, achei que fosse isso. A dica de somar 1 dia e 1 hora eu dei pela primeira vez para a minha esposa, que teve um problema com o dia 10/10/2004.

Criado 7 de janeiro de 2005
Ultima resposta 10 de jan. de 2005
Respostas 4
Participantes 2