如何从文本中检索各种日期和时间值

How to retrieve all kinds of dates and temporal values from text

我想从一组字符串中检索日期和其他时间实体。这是否可以在不解析 JAVA 中的日期字符串的情况下完成,因为大多数解析器处理的输入模式范围有限。但是输入是一个手动输入,因此在这里是模棱两可的。

输入可以是这样的:

12th Sep |mid-March |12.September.2013

Sep 12th |12th September| 2013

Sept 13 |12th, September |12th,Feb,2013

我在 Java 中查看了很多关于查找日期的答案,但大多数答案都没有涉及如此广泛的输入模式。

我试过使用 SimpleDateFormat class 并使用一些 parse() 函数来检查 parse 函数是否中断,这意味着它不是日期。我试过使用 regex 但我不确定它是否适合这种情况。我还使用 ClearNLP 来注释日期,但它没有提供可靠的注释集。

获取这些值的最接近方法可能是使用 Chain of responsibility,如下所述。是否有一个库具有一组日期模式。也许我可以使用它?

您可以实现对所有您能想到的模式可能性的支持,然后记录...好的,这些都是我的模块支持的模式。然后,您可以为所有其他可能性抛出一些 RuntimeException

然后...以迭代的方式,您可以将 运行 您的模块保留在输入数据上,并继续添加对更多日期格式的支持,直到它停止引发任何 RuntimeException

我认为如果你想让它保持相当简单的话,这是你能在这里做的最好的事情。

我可以向你推荐你的问题的非常好的实现,不幸的是在波兰:http://koziolekweb.pl/2015/04/15/throw-to-taki-inny-return/

您可以使用 google 翻译器:

https://translate.google.pl/translate?sl=pl&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=http%3A%2F%2Fkoziolekweb.pl%2F2015%2F04%2F15%2Fthrow-to-taki-inny-return&edit-text=

那里的代码看起来很不错:

private static Date convertStringToDate(String s) {                           
    if (s == null || s.trim().isEmpty()) return null;                         
    ArrayList<String> patterns = Lists.newArrayList(YYYY_MM_DD_T_HH_MM_SS_SSS,
            YYYY_MM_DD_T_HH_MM_SS                                             
            , YYYY_MM_DD_T_HH_MM                                              
            , YYYY_MM_DD);                                                    
    for (String pattern : patterns) {                                         
        try {                                                                 
            return new SimpleDateFormat(pattern).parse(s);                    
        } catch (ParseException e) {                                          
        }                                                                     
    }                                                                         
    return new Date(Long.valueOf(s));                                         
}

解决这个问题的一个干净和模块化的方法是使用链, 链中的每个元素都试图将输入字符串与正则表达式进行匹配, 如果正则表达式与输入字符串匹配,那么您可以将输入字符串转换为可以提供 SimpleDateFormat 的内容,以将其转换为您喜欢的数据结构(日期?或更适合您需要的不同时间表示)和 return它,如果正则表达式与链元素不匹配,则只委托给链中的下一个元素。

链中每个元素的职责只是针对字符串测试正则表达式,给出结果或要求链中的下一个元素试一试。

可以轻松创建和组合链,而无需更改链中每个元素的实现。

最后的结果与@KirkoR 的响应相同,代码多了 'bit' (:D),但采用了模块化方法。 (与 try/catch 相比,我更喜欢正则表达式方法)

一些参考:https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern

是的!我终于提取了各种 dates/temporal 值,它们可以像 :

一样通用

mid-March | Last Month | 9/11

具体如:

11/11/11 11:11:11

这最终发生了,因为来自 GATE and JAPE

的很棒的库

我在 JAPE 中创建了一个更宽松的注释规则说 'DateEnhanced' 以包括某些类型的日期,例如“2001 年 2 月 9 日或 11 日”,并使用 Chaining Java R.H.S 上的正则表达式。 'DateEnhanced' 注释 JAPE RULE,以过滤一些不需要的输出。

    mark.util.DateParser dp = new DateParser();
    ParsePositionEx parsePosition = new ParsePositionEx(0);
    Date startDate = dp.parse("12.September.2013", parsePosition);
    System.out.println(startDate);

output: Thu Sep 12 17:18:18 IST 2013

mark.util.Dateparser 是 DateNormalizer PR 使用的库的一部分。所以在 Jape 文件中,我们只需要导入它。