Java SimpleDateFormat всегда возвращает январь за месяц - PullRequest
21 голосов
/ 24 августа 2010

Я работаю над тем, чтобы взять значение даты (createWhen) из Active Directory и перевести его в дату Java, чтобы получить список учетных записей, созданных между двумя датами.Все работает нормально, за исключением одного метода: метода, в котором я иду от даты AD к дате Java.Метод выглядит следующим образом:

private Date getParsedDate(String givenString) {
    System.out.println("Value from AD is: " + givenString);
    Date parsedDate = null;
    String formattedString = this.formatDateString(givenString);
    System.out.println("Formatted String is: " + formattedString);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/DD");
    try {
        parsedDate = sdf.parse(formattedString);
        System.out.println("Final date string is: " + parsedDate.toString());
    } catch (ParseException ex) {
        ex.printStackTrace();
    }
    return parsedDate;
}

И, для одного куска произвольных данных из AD:

Value from AD is: 20050912190509.0Z

Formatted String is: 2005/09/12

Final date string is: Wed Jan 12 00:00:00 EST 2005

Очевидно, что он правильно подбирает день и год (и если я решу включить часы / минуты / секунды, то это также правильно включает и их), но каждую отдельную дату по какой-то причине его помещают в январе.

Теперь я уверен, что моя ошибка довольно проста, но я перепроверил форматирование примерно в десять раз, и я нахожусь в точке, где япросто больше не вижуМожет ли вторая пара глаз, надеюсь, просмотреть мой код и указать, где я ошибаюсь, чтобы получить месяц с такой грубой ошибкой?

Спасибо.

Ответы [ 3 ]

50 голосов
/ 24 августа 2010

Изменить строку шаблона с «гггг / мм / дд» на «гггг / мм / дд»

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
5 голосов
/ 13 июля 2016

Убедитесь, что вы не используете «мм» вместо «ММ» или «МММ».Маленькое m обозначает минуты, а заглавные буквы M обозначают месяц.

1 голос
/ 11 декабря 2017

TL; DR

    LocalDate parsedDate = OffsetDateTime
            .parse("20050912190509.0Z", DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX"))
            .toLocalDate();

Это дает LocalDate из 2005-09-12.

java.time

Я помогаю современным ответом. Ответ Suhas Phartale правильный и был хорошим ответом, когда он был написан 7 лет назад. Теперь общеизвестно хлопотный класс SimpleDateFormat давно устарел, и у нас намного лучше в java.time, современном Java-API даты и времени. Я настоятельно рекомендую вам использовать это вместо старых классов даты и времени.

Подробнее

Судя по вашему коду, вы переформатируете строку из AD перед ее анализом. В этом нет необходимости, строка из AD может быть проанализирована напрямую. Мы могли бы проанализировать его непосредственно в LocalDate, но я рекомендую разобрать его в OffsetDateTime, чтобы получить время и смещение от строки; как вы можете видеть, это может быть непосредственно преобразовано в LocalDate впоследствии. LocalDate - это дата без времени суток, поэтому она лучше соответствует вашим требованиям, чем старый класс Date.

Строка в UTC (обозначается Z в конце). Выше приведена дата из строки, то есть дата в формате UTC. Если вместо этого вы хотели указать дату, которая была в вашем местном часовом поясе, когда это было 12 сентября, 19:05 по UTC:

    LocalDate parsedDate = OffsetDateTime.parse(givenString, adDateTimeFormatter)
            .atZoneSameInstant(ZoneId.of("America/Coral_Harbour"))
            .toLocalDate();

Я предположил, что мы объявили форматер статическим полем:

private static final DateTimeFormatter adDateTimeFormatter
        = DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX");

В этом случае результат тот же, для других часовых поясов он не будет. Пожалуйста, замените свой часовой пояс на America / Coral_Harbour. Чтобы использовать настройку часового пояса JVM, укажите ZoneId.systemDefault(). Однако помните, что этот параметр может быть изменен другими частями вашей программы или другими программами, работающими в той же JVM, так что это хрупко.

И пункт из ответа Suhas Phartale действителен и в java.time: строки шаблона формата чувствительны к регистру, и мне нужно было использовать строчные буквы dd для дня месяца.

Учебник

Подробнее о java.time в руководстве по Oracle и / или поиске других ресурсов в сети.

...