2016-01-07 3 views
2

Как порядок опциональных шаблонов в DateTimeFormatter влияет на операцию синтаксического анализа?Важность заказа при использовании нескольких необязательных шаблонов

Я запускал эту программу и задавался вопросом, почему последняя строка генерирует исключение, но не первые три.

public static void main(String[] args) { 
    String p1 = "[EEEE][E] dd-MM-yyyy"; 
    String p2 = "[E][EEEE] dd-MM-yyyy"; 
    String date1 = "Thu 07-01-2016"; 
    String date2 = "Thursday 07-01-2016"; 
    parse(date1, p1); //OK 
    parse(date1, p2); //OK 
    parse(date2, p1); //OK 
    parse(date2, p2); //Exception 
} 

private static void parse(String date, String pattern) { 
    DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH); 
    System.out.println(fmt.parse(date)); 
} 

Исключение на последней строке:

java.time.format.DateTimeParseException: Текст 'четверг 07-01-2016' не может быть разобрано по индексу 3

+1

Мне было бы приятно, если бы 'java.time' предлагал' DateTimeFormatter' с резервными шаблонами (например, jodatime). –

+1

@SotiriosDelimanolis Там, где есть вопрос о добавлении поддержки для «OR» в разборе: [JDK-8132536] (https://bugs.openjdk.java.net/browse/JDK-8132536) – Tunaki

+0

@ Сайт отслеживания ошибок Tunaki Java ооо медленно. Надеемся, что запрос будет принят. –

ответ

3

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

  • Рассмотрим первый формат "[EEEE][E] dd-MM-yyyy".

    • "Thu 07-01-2016": АНИ пытается найти, если первый необязательный раздел "[EEEE]" может быть подобран. Цитата из DateTimeFormatter Javadoc о текстовом токере

      Ровно 4 буквы шаблонов будут использовать полную форму.

      который в этом случае является полной формой дня недели. Это не соответствует "Thu", так что необязательный раздел будет пропущен. Второй необязательный раздел, однако, равен "[E]", и все еще цитирует

      Менее 4 букв шаблонов будут использовать короткую форму.

      , так что это будет соответствовать "Thu". Таким образом, строка для разбора может быть правильно понята

    • "Thursday 07-01-2016": она такая же, как и выше, за исключением того, что она будет соответствовать первому необязательному разделу с "Thursday". Но API все равно продолжит поиск допустимого раздела для следующего необязательного, "[E]", и он не найдет, так что необязательный раздел будет пропущен.
  • Рассмотрим теперь второй формат "[E][EEEE] dd-MM-yyyy".
    • "Thu 07-01-2016": АНИ пытается найти, если первый необязательный раздел "[E]" может быть согласован и он работает на "Thu". Как и выше, API теперь попытается найти совпадение для "[EEEE]", но он не найдет ничего, поэтому необязательный раздел будет пропущен.
    • "Thursday 07-01-2016": API пытается снова совместить "[E]", и вот что происходит: он соответствует. "Thursday" начинается с "Thu", чтобы форматер смог найти совпадение. Но затем он пытается разобрать остаток, который равен "rsday 07-01-2016". [EEEE] необязательный раздел не будет соответствовать, поэтому он будет пропущен. Тогда он терпит неудачу с пространством, потому что нет места на том, что осталось (вместо этого есть "r").

Так что, если вы запустите ваш код с

parse("ThuThursday 07-01-2016", "[E][EEEE] dd-MM-yyyy"); 

вы увидите, что это работает: "[E]" соответствует "Thu" и "[EEEE]" соответствует "Thursday".

Обратите внимание, как сообщение об исключении также намекает на это (курсив мой):

java.time.format.DateTimeParseException: Текст «четверг 07-01-2016» не может быть разобран индексом 3

Индекс 3 соответствует "r" из "rsday" так это означает, что он был в состоянии разобрать, вплоть до этого момента.

1

Порядок дополнительных форматов вопросы:

Когда анализатор формата [E][EEEE] dd-MM-yyyy разбирает "Thursday 07-01-2016" то

  • потребляет Thu, используя дополнительный раздел [E]
  • скачет [EEEE], так как он не может распознать длинный день-неделю
  • теперь ожидает, что пространство и не так как он видит r и, следовательно, вызывает исключение с индексом ошибки 3

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

2

Как порядок опциональных шаблонов в DateTimeFormatter влияет на операцию синтаксического анализа?

Парсер пытается сопоставить каждый необязательный раздел в порядке его появления в шаблоне.

Обратите внимание, что строка «Четверг» начинается с «Thu», которая может быть сопоставлена ​​фрагментом шаблона «E». Затем обратите внимание на то, что ошибка совпадения указана в индексе 3, что соответствует «r» в «Четверге». Что происходит в случае ошибки, так это то, что синтаксический анализатор сопоставляет первые три символа строки с первым необязательным сектором, пропускает второй необязательный раздел, потому что он не соответствует следующей части строки, а затем не может соответствовать «r».

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

Обратите внимание, что оба ваших шаблона более разрешительны, чем вы хотите. Например, ваш шаблон p1 будет соответствовать строке "ThursdayThu 07-01-2016".

Смежные вопросы