Data Parsing/Formating com fuso horário e SimpleDateFormat fornece resultados diferentes em torno do interruptor DST

StackOverflow https://stackoverflow.com/questions/2356672

  •  23-09-2019
  •  | 
  •  

Pergunta

Fui três postagens sobre o fuso horário e o SimpleDateFormat no Google e o Stack Overflow, mas ainda não entendi o que estou fazendo de errado. Estou trabalhando em algum código herdado e há um método parsedado, que fornece resultados errados.

Anexei o Sample Junit, que estou tentando usar, investigar o problema.

Primeiro método (testParSestrangedate_ibm_ibm) usa a implementação da IBM para formatar a saída de parsedado método. Segundo formatos, saída com a implementação do Sun.

O uso do Sun SimpleDateFormat nos dá um tempo diferente em uma hora (que pode estar relacionado à economia de luz diurna). Definindo o fuso horário padrão para as correções de implementação da IBM parsedado Método (Simplesmente Uncomment 3 linhas no método setUpDefaultTZ).

Tenho certeza de que não é um bug, mas estou fazendo algo errado.

@Test
public void testParseStrangeDate_IBM_IBM() {
    setupDefaultTZ();

    Calendar date = parseDate("2010-03-14T02:25:00");
    com.ibm.icu.text.SimpleDateFormat dateFormat = new com.ibm.icu.text.SimpleDateFormat(
            "yyyy-MM-dd HH:mm:ss");

    // PASSES:
    assertEquals("2010-03-14 02:25:00", dateFormat.format(date.getTime()));
}

@Test
public void testParseStrangeDate_SUN_SUN() {
    setupDefaultTZ();

    Calendar date = parseDate("2010-03-14T02:25:00");
    java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat(
            "yyyy-MM-dd HH:mm:ss");

    // FAILS:
    assertEquals("2010-03-14 02:25:00", dateFormat.format(date.getTime()));
}

public static Calendar parseDate(String varDate) {
    Calendar cal = null;
    try {
        // DOES NOT MAKE ANY DIFFERENCE:
        // com.ibm.icu.text.SimpleDateFormat simpleDateFormat = new
        // com.ibm.icu.text.SimpleDateFormat(
        // "yyyy-MM-dd'T'HH:mm:ss");
        java.text.SimpleDateFormat simpleDateFormat = new java.text.SimpleDateFormat(
                "yyyy-MM-dd'T'HH:mm:ss", Locale.US);
        Date date = simpleDateFormat.parse(varDate);
        cal = GregorianCalendar.getInstance();
        cal.setTimeInMillis(date.getTime());
        System.out.println("CAL: [" + cal + "]");
    } catch (ParseException pe) {
        pe.printStackTrace();
    }
    return cal;
}

private void setupDefaultTZ() {
    java.util.TimeZone timeZoneSun = java.util.TimeZone.getTimeZone("America/Chicago");
    java.util.TimeZone.setDefault(timeZoneSun);

    // UNCOMMENTING THIS ONE FIXES SUN PARSING ??
    // com.ibm.icu.util.TimeZone timeZoneIbm = com.ibm.icu.util.TimeZone
    // .getTimeZone("America/Chicago");
    // com.ibm.icu.util.TimeZone.setDefault(timeZoneIbm);

    Locale.setDefault(Locale.US);
}
Foi útil?

Solução

O problema é que você especificou um tempo que não existe. Os relógios avançam para que as 2 da manhã se tornem das 3h - 2h25 nunca acontecem.

Agora, existem várias opções para o que poderia acontecer aqui. Dentro Tempo noda Acredito que lançaríamos uma exceção (esse é o plano de qualquer maneira); Eu acredito Joda Time (Uma API Java muito melhor do que a data/calendário/SimpleDateFormat - você deve considerar migrar para ela, se puder), dará às 3:25 da manhã, ou seja, 25 minutos após a transição.

O que você querer para acontecer quando você recebe uma combinação de data/hora que é impossível devido à transição do DST? Nesta situação, é difícil saber com certeza o que você quer dizer com os resultados "errados". Eu diria que seu teste de unidade é um tanto falho - não há tempo possível que deve ser formatado até aquele momento.

Meu palpite sobre o motivo pelo qual o fuso horário da IBM "funciona" é que ele pode usar dados antigos do fuso horário, antes de os EUA mudarem suas transições DST. Tente usar 28 de março, que é quando eu acho gostaria Caso contrário - você provavelmente encontrará os testes falham da mesma maneira com a zona IBM, mas não com o sol :) (como a zona do sol não a considera uma transição DST.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top