Date + Calendar + Timezone

3 respostas
danieldestro

Caros,

Meu ambiente está no timezone Americas/Sao_Paulo (GMT-3), porém preciso mandar/receber uma data de outro sistema que trata a data como GMT.

Gostaria de usar as próprias APIs do Java para tratar destes detalhes, mas, na realidade, não estout endo sucesso.

Se pego a data/hora corrente do sistema, forçando o timezone GMT, a data que me vem não corresponde à data GMT.

Exemplo:

TimeZone tz = TimeZone.getDefault();
Date dt = Calendar.getInstance( tz ).getTime();
System.out.println( dt );
System.out.println( dt.getTime() );

tz = TimeZone.getTimeZone("GMT");
dt = Calendar.getInstance( tz ).getTime();
System.out.println( dt );
System.out.println( dt.getTime() );

Em ambos os timezones, a data me aparece igual, quando eu esperava ter uma data diferente no timezone GMT.

Wed Aug 25 10:09:55 BRT 2010 1282741795207 Wed Aug 25 10:09:55 BRT 2010 1282741795207

O que pode estar acontecendo? Qual seria a melhor solução para, a partir da data/hora corrente do meu sistema, independente do meu timezone, eu pegar a data/hora correspondente do timezone GMT?

3 Respostas

danieldestro

Bom, como eu só preciso formatar a data como uma String para enviar, eu resolvi desta forma:

SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'"); formatter.setTimeZone(TimeZone.getTimeZone("GMT"));

No entanto não fico confortável em saber que os testes anteriores falharam. Ainda não entendi o motivo.

davidbuzatto

Oi Daniel,

Realmente MUITO estranho.
Fiz alguns testes e parece que o Calendar.getInstance( TimeZone ) não usa o TimeZone passado, mas sim o TimeZone padrão.

Segue o código:

TimeZone.setDefault( TimeZone.getTimeZone( "GMT" ));
TimeZone tz = TimeZone.getDefault();
Date dt = Calendar.getInstance( tz ).getTime();
System.out.println( tz.getDisplayName() );
System.out.println( dt );
System.out.println( dt.getTime() );

TimeZone.setDefault( TimeZone.getTimeZone( "GMT-3" ));
tz = TimeZone.getDefault();

// passa o default, mas não é o parâmetro passado que influencia
// mas sim o setDefault de TimeZone
dt = Calendar.getInstance( tz ).getTime();
System.out.println( tz.getDisplayName() );
System.out.println( dt );
System.out.println( dt.getTime() );

// default
dt = Calendar.getInstance().getTime();
System.out.println( tz.getDisplayName() );
System.out.println( dt );
System.out.println( dt.getTime() );

// não muda
dt = Calendar.getInstance( TimeZone.getTimeZone( "GMT" )).getTime();
System.out.println( tz.getDisplayName() );
System.out.println( dt );
System.out.println( dt.getTime() );

Estou dando uma olhada nos fontes do Calendar e do GregorianCalendar para ver se acho o que pode estar acontecendo.

[]´s

davidbuzatto

Olhe os métodos e construtores que são chamados (em ordem).

public static Calendar getInstance(TimeZone zone)
{
    return createCalendar(zone, Locale.getDefault());
}

private static Calendar createCalendar(TimeZone zone,
                                       Locale aLocale)
{
    // If the specified locale is a Thai locale, returns a BuddhistCalendar
    // instance.
    if ("th".equals(aLocale.getLanguage())
        && ("TH".equals(aLocale.getCountry()))) {
        return new sun.util.BuddhistCalendar(zone, aLocale);
    } else if ("JP".equals(aLocale.getVariant())
               && "JP".equals(aLocale.getCountry())
               && "ja".equals(aLocale.getLanguage())) {
        return new JapaneseImperialCalendar(zone, aLocale);
    }	    

    // else create the default calendar
    return new GregorianCalendar(zone, aLocale);	
}

public GregorianCalendar(TimeZone zone, Locale aLocale) {
    super(zone, aLocale);
    gdate = (BaseCalendar.Date) gcal.newCalendarDate(zone);
    setTimeInMillis(System.currentTimeMillis());
}

// construtor chamando no construtor acima
protected Calendar(TimeZone zone, Locale aLocale)
{
    fields = new int[FIELD_COUNT];
    isSet = new boolean[FIELD_COUNT];
    stamp = new int[FIELD_COUNT];

    this.zone = zone;
    setWeekCountData(aLocale);
}
O newCalendarDate está definido na classe abstrata sun.util.calendar.CalendarSystem :( Não consegui encontrar quem a implementa :( Parece que o buraco é mais embaixo...

[]´s

Criado 25 de agosto de 2010
Ultima resposta 25 de ago. de 2010
Respostas 3
Participantes 2