Синтаксический анализ / форматирование даты с TimeZone и SimpleDateFormat дают разные результаты в отношении перехода на летнее время - PullRequest
3 голосов
/ 01 марта 2010

Я прочитал несколько постов о TimeZone и SimpleDateFormat в Google и Stack Overflow, но все равно не понял, что я делаю неправильно. Я работаю над устаревшим кодом, и есть метод parseDate, который дает неправильные результаты.

Я приложил образец JUnit, который я пытаюсь использовать для расследования проблемы.

Первый метод (testParseStrangeDate_IBM_IBM) использует реализацию IBM для форматирования вывода метода parseDate . Вывод второго формата с реализацией Sun.

Использование Sun SimpleDateFormat дает нам разное время на час (что может быть связано с переходом на летнее время). Установка TimeZone по умолчанию для метода исправлений реализации IBM parseDate (просто раскомментируйте 3 строки в методе setupDefaultTZ).

Я уверен, что это не ошибка, но я делаю что-то не так.

@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);
}

1 Ответ

2 голосов
/ 01 марта 2010

Проблема в том, что вы указали время, которого не существует. Часы идут так, что 2 часа ночи становятся 3 часа ночи - 2:25 утра никогда не бывает.

Теперь есть различные варианты того, что может здесь произойти. В Время Ноды Я полагаю, что мы бросим исключение (это план в любом случае); Я полагаю, что Joda Time (гораздо лучший Java API, чем Date / Calendar / SimpleDateFormat - вам следует подумать о переходе на него, если возможно) даст вам 3:25 утра, то есть 25 минут после перехода.

Что бы вы хотели бы, чтобы произошло, когда вам дали комбинацию даты / времени, которая невозможна из-за перехода на летнее время? В этой ситуации трудно точно знать, что вы подразумеваете под «неправильными» результатами. Я бы сказал, что ваш модульный тест несколько ошибочен - нет никакого возможного времени, которое должно быть отформатировано к этому времени.

Мое предположение относительно того, почему часовой пояс IBM «работает», заключается в том, что он может использовать старые данные о часовых поясах до того, как США изменили свои переходы DST. Попробуйте использовать 28 марта, и тогда я думаю, что было бы иначе - вы, вероятно, обнаружите, что тесты провалились так же, как в зоне IBM, но не в зоне Sun :) Солнечная зона не будет рассматривать это как переход на летнее время.)

...