Подтвердить что ты не робот

Множество исключений, которые выбрали строку даты синтаксического анализа

Я пытаюсь разобрать строку в дату в конструкторе объекта, который мы будем называть Example. Вот код

private static final SimpleDateFormat sdf = new SimpleDateFormat(
        "yyyy-MM-dd HH:mm:ss");

private long time;

public Example(String date) {
    try {
        this.time = sdf.parse(date).getTime();
    } catch (Exception e) {
        logger.log(Level.WARNING, "Exception while parsing date " + date, e);
    }
}

Теперь я создаю эти объекты в экземпляре Tomcat (независимо от того, имеет ли это значение или нет).

Я получаю следующие типы исключений

Fri Jul 06 15:13:48 EDT 2012 WARNING: Exception while parsing date 2012-07-06 18:57:31
java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Long.parseLong(Long.java:431)
    at java.lang.Long.parseLong(Long.java:468)
    at java.text.DigitList.getLong(DigitList.java:177)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1297)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)
    at java.text.DateFormat.parse(DateFormat.java:335)
    at ...
Fri Jul 06 15:13:48 EDT 2012 WARNING: Exception while parsing date 2012-07-06 19:00:07
java.lang.NumberFormatException: multiple points
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1082)
    at java.lang.Double.parseDouble(Double.java:510)
    at java.text.DigitList.getDouble(DigitList.java:151)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1302)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1934)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)
    at java.text.DateFormat.parse(DateFormat.java:335)
    at ...
Fri Jul 06 15:13:48 EDT 2012 WARNING: Exception while parsing date 2012-07-06 19:13:21
java.lang.ArrayIndexOutOfBoundsException: -1
    at java.text.DigitList.fitsIntoLong(DigitList.java:212)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1295)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1934)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)
    at java.text.DateFormat.parse(DateFormat.java:335)
    at ...
Fri Jul 06 15:48:06 EDT 2012 WARNING: Exception while parsing last check string 2012-07-06 19:08:08
java.lang.NumberFormatException: For input string: ".200172E4.200172"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1222)
    at java.lang.Double.parseDouble(Double.java:510)
    at java.text.DigitList.getDouble(DigitList.java:151)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1302)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)
    at java.text.DateFormat.parse(DateFormat.java:335)
    at ...

Таким образом, он не подходит для дат

2012-07-06 18:57:31
2012-07-06 19:00:07
2012-07-06 19:13:21
2012-07-06 19:08:08

Однако, если я создаю unit test, я получаю следующие значения для time из этих строк

1341615451000
1341615607000
1341616401000
1341616088000

Итак, объект SimpleDateFormat работает... но не на сервере? Я заметил, что эта проблема возникает при запуске сервера, а затем не позже, если это вообще помогает. Не совсем уверен, что делать дальше.

Использование обновлений Tomcat 7.0 и Java 1.6.

4b9b3361

Ответ 1

SimpleDateFormat не является потокобезопасным, как описано https://www.palantir.com/2007/07/simpledateformat-is-not-thread-safe/ Иногда, действительно странное или нелогичное поведение при использовании "статических" объектов происходит из concurrency проблем

Чтобы разрешить такой случай, каждый раз используйте новый экземпляр (это лучше синхронизации, так как синхронизация может вызвать проблему с узким местом)

Ответ 2

SimpleDateFormat не является потокобезопасным: см. Javadoc.

Ответ 3

Как и в случае с Java 8+, было бы лучше предпочесть решение на основе java.time.

Классы в java.time потокобезопасны.

Вы можете добиться эквивалентного удаления даты таким образом:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

...

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

LocalDateTime date = LocalDateTime.parse(str, dockerDateFormatter);

а затем запросите нужные поля из date.

Подробнее в JavaDoc для DateTimeFormatter и LocalDateTime.

Еще один ресурс TL;DR с двумя готовыми к использованию примерами.