Почему я получаю исключение ParseException при использовании SimpleDateFormat для форматирования даты и последующего ее анализа? - PullRequest
8 голосов
/ 03 июня 2010

Я отлаживал некоторый существующий код, для которого модульные тесты не выполнялись в моей системе, но не в системах коллег. Основная причина в том, что SimpleDateFormat генерирует ParseExceptions при разборе дат, которые должны быть проанализированы. Я создал модульный тест, демонстрирующий сбой кода в моей системе:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import junit.framework.TestCase;

public class FormatsTest extends TestCase {

    public void testParse() throws ParseException {
        DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss.SSS Z");
        formatter.setTimeZone(TimeZone.getDefault());
        formatter.setLenient(false);

        formatter.parse(formatter.format(new Date()));
    }
}

Этот тест вызывает исключение ParseException в моей системе, но успешно выполняется в других системах.

java.text.ParseException: Unparseable date: "20100603100243.118 -0600"
    at java.text.DateFormat.parse(DateFormat.java:352)
    at FormatsTest.testParse(FormatsTest.java:16)

Я обнаружил, что могу setLenient(true), и тест пройдёт успешно. setLenient(false) - это то, что используется в производственном коде, который имитирует этот тест, поэтому я не хочу его менять.

Ответы [ 3 ]

6 голосов
/ 03 июня 2010

--- Отредактировано после ответа, указывающего, что разработчик использует виртуальную машину Java J9 1.5.0 IBM ---

В JVM IBM J9, похоже, есть несколько ошибок и несовместимостей в процедуре разбора DateFormat, которую SimpleDateFormat, вероятно, наследует, потому что это подкласс DateFormat. Некоторые свидетельства в поддержку того, что J9 IBM работает не совсем так, как можно было бы ожидать от других JVM (например, SunS HotSpot JVM), можно увидеть здесь .

Обратите внимание, что эти ошибки и несовместимости даже не согласованы в JVM J9, иными словами, логика форматирования IBM J9 может фактически генерировать отформатированные времена, которые не совместимы с логикой синтаксического анализа IBM J9.

Кажется, что люди, которые связаны с JVM IBM J9, имеют тенденцию обходить ошибку в JVM, не используя DateFormat.parse (...) (или SimpleDateFormat.parse (...)). Вместо этого они обычно используют java.util.regex.Matcher для анализа полей вручную.

Возможно, более поздняя версия J9 JVM решит проблему, возможно, нет.

--- Исходный пост следует ---

Забавно, тот же код изменен на:

import java.util.Date;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.text.ParseException;

public class FormatsTest {

 public void testParse() throws ParseException {
  DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss.SSS Z");
  formatter.setTimeZone(TimeZone.getDefault());
  formatter.setLenient(false);
  System.out.println(formatter.format(new Date()));

  formatter.parse(formatter.format(new Date()));
 }

 public static void main(String[] args) throws Exception {
   FormatsTest test = new FormatsTest();
   test.testParse();
 }

}

отлично работает в моей системе. Держу пари, что это что-то в вашей среде. Либо вы компилируете код для одного основного выпуска JVM и запускаете его для другого (что может вызвать некоторые проблемы, поскольку библиотеки могут устареть), либо система, на которой вы его запускаете, может странным образом сообщать информацию о часовом поясе.

Наконец, вы можете подумать, используете ли вы очень раннюю версию JVM. Иногда ошибки появляются в разных версиях, и они исправляются в более поздних выпусках. Не могли бы вы изменить свой вопрос, включив в него информацию "java -version" для вашей системы?

В любом случае, оба из них являются только образованными догадками. Код должен работать как написано.

1 голос
/ 03 июня 2010

Вероятно, это должно быть ошибкой в ​​IBM J9 VM относительно класса SimpleDateFormat.

Этот пост показывает похожую проблему и говорит, что она должна быть исправлена ​​в v6.

Вы можете найти список изменений для нескольких выпусков здесь .

Я вижу, что есть число, связанное с DateFormat. Поэтому вам, вероятно, следует подать отчет об ошибке или что-то в IBM, чтобы они дали вам патч.

0 голосов
/ 04 августа 2011

Проверьте переменную среды LANG вашего компьютера и удаленного компьютера.

Дата анализируется в соответствии с локалью, поэтому «июль» работает как июль, только если ваш LANG установлен на английский, в противном случае возникает ParseException.

Вы можете выполнить быстрый тест, запустив export LANG="en_US.UTF-8" и запустив вашу программу.

Вы также можете установить локаль программно, используя следующий метод: DateFormat.getDateInstance (int, java.util.Locale)

...