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

Как определить дату из строки в Java

Недавно меня бросает вызов довольно "легкой" проблемой. Предположим, что есть предложения (сохраненные в String), и мне нужно выяснить, существует ли какая-либо дата в этой строке. Проблемы заключаются в том, что дата может быть в разных форматах. Некоторые примеры показаны в списке:

  • 12 июня 1956 года
  • Лондон, 21 октября 2014 года.
  • 13 октября 1999 г.
  • 01/11/2003

Стоит упомянуть, что они содержатся в одной строке. Так что в качестве примера это может быть как:

String s = "This event took place on 13 October 1999.";

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

Одним из решений, которое я до сих пор не пробовал, является создание регулярных выражений и попытка найти совпадение в строке. Не уверен, насколько это решение может снизить производительность.

Что может быть хорошим решением, которое я, вероятно, должен рассмотреть? Кто-нибудь сталкивался с подобной проблемой раньше и какие решения вы нашли?

Одно можно сказать наверняка, что нет времени, поэтому единственной интересной частью является дата.

4b9b3361

Ответ 1

Использование библиотеки natty.joestelmach.com

Natty - это парсер с естественным языком, написанный на Java. Учитывая выражение даты, natty будет применять стандартные методы распознавания языка и перевода для составления списка соответствующих дат с необязательной информацией синтаксиса и синтаксиса.

import com.joestelmach.natty.*;

List<Date> dates =new Parser().parse("Start date 11/30/2013 , end date Friday, Sept. 7, 2013").get(0).getDates();
        System.out.println(dates.get(0));
        System.out.println(dates.get(1));

//output:
//Sat Nov 30 11:14:30 BDT 2013
//Sat Sep 07 11:14:30 BDT 2013

Ответ 3

Если это только одна строка, вы можете использовать регулярное выражение, как вы упомянули. Необходимо найти разные выражения формата даты. Вот некоторые примеры: Регулярные выражения - даты

Если это документ или большой текст, вам понадобится парсер. Вы можете использовать Лексический анализ.

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

Ответ 4

Я сделал это раньше с хорошими precision и recall. Вам понадобится GATE и его плагин ANNIE.

  • Используйте инструмент инструмента GATE для создания файла .GAPP, который будет содержать ваши processing resources.

  • Используйте файл .GAPP для использования извлеченного Date набор аннотаций.

Шаг 2 можно сделать следующим образом:

Corpus corpus = Factory.newCorpus("Gate Corpus");
Document gateDoc = Factory.newDocument("This event took place on 13 October 1999.");
corpus.add(gateDoc);
File pluginsHome = Gate.getPluginsHome();
File ANNIEPlugin = new File(pluginsHome, "ANNIE");
File AnnieGapp = new File(ANNIEPlugin, "Test.gapp");
AnnieController =(CorpusController) PersistenceManager.loadObjectFromFile(AnnieGapp);
AnnieController.setCorpus(corpus);
AnnieController.execute();

Позже вы можете увидеть извлеченные аннотации следующим образом:

AnnotationSetImpl ann = (AnnotationSetImpl) gateDoc.getAnnotations();
System.out.println("Found annotations of the following types: "+ gateDoc.getAnnotations().getAllTypes());

Я уверен, что вы можете сделать это легко с помощью встроенного набора аннотаций Date. Он также очень полезен.

Чтобы увеличить набор аннотаций Date, создайте правило аннотации lenient в JAPE скажите 'DateEnhanced' из встроенной аннотации ANNIE Date включить определенные типы дат типа "9/11" и использовать регулярное выражение "Цепочка Java" на RHS аннотаций "DateEnhanced" JAPE RULE, чтобы отфильтровать некоторые нежелательные выходы (если есть).