Метод синтаксического анализа класса DateFormat
, как ожидается, игнорирует завершающий текст , если ему удастся проанализировать дату с начала строки.
API документы являются уклончивыми:
Анализирует текст с начала данной строки, чтобы получить дату.Метод может не использовать весь текст данной строки.
Я думал, что "может" означает - "если конечный текст существует и не является частью даты (не может бытьинтерпретируется как таковой).Но похоже, что это «может» гораздо более непредсказуемо.
Учитывая
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Это работает неправильно (неожиданно):
System.out.println(df.parse("2019-12-112"));
Output: Sat Mar 21 00:00:00 MSK 2020
Хотя это работает нормально (какожидается):
System.out.println(df.parse("2019-12-11sometext"));
Output: Wed Dec 11 00:00:00 MSK 2019
Если остальная часть анализируемого текста состоит из цифр, кажется, что он всегда не сможет правильно проанализировать (что дает разные ошибочные результаты):
System.out.println(df.parse("2019-12-1189"));
System.out.println(df.parse("2019-12-11234"));
Output:
Fri Mar 03 00:00:00 MSK 2023
Fri Sep 02 00:00:00 MSK 2050
Теперь setLenient()
ведет себя так:
- Если за (правильной) датой следует пробел или буквы, то настройка setLenient () не имеет значения .Все анализируется правильно и без исключений для обоих setLenient (true / false).
- Но , если за (правильной) датой сразу следует цифра (цифры), тогда setLenient () делает (неожиданную) разницу : default (true) не приводит ни к исключению, ни к неправильному (!) Результату синтаксического анализа, но setLenient (false) woud приводит к
ParseException: Unparseable date: "2019-12-111"
, что также странно (дата верна, а игнорирование завершающего текста было своего рода обещанным API) ...
Date parse(String source, ParsePosition pos)
ведет себя абсолютно идентично Date parse(String source)
во всех вышеупомянутых случаях (включая реакцию на setLenient) для единственного (и ожидаемого) исключения, которое где one-arg parse () throws ParseException , это два аргумента parse () возвращает null (что является его реакцией на неправильный формат даты в начале строкидля анализа).
Также стоит отметить, что после вызова mydateFormat.parse("2019-12-11234", pos)
(с setLenient (true) ), pos.getIndex()
возвращает 13 - что указывает "за" 234 часть, что означает это относится к 234 номиналуt как «-dd» часть «yyyy-MM-dd» в new SimpleDateFormat("yyyy-MM-dd")
.
PS Я знаю, что это устаревший API даты / времени, и я предпочитаю java.time вместо Date /Calendar / DateFormat и т. Д. Но он все еще широко представлен в унаследованном коде для поддержки в случаях, когда рефакторинг невозможен.