Анализ / форматирование даты с помощью часового пояса и SimpleDateFormat дают разные результаты при переключении DST

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

  •  23-09-2019
  •  | 
  •  

Вопрос

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

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

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

Использование Sun's SimpleDateFormat дает нам время, отличающееся на час (что может быть связано с экономией дневного света).Установка часового пояса по умолчанию для исправлений реализации IBM Проанализированный метод (просто раскомментируйте 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);
}
Это было полезно?

Решение

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top