Java 识别任意日期字符串
我需要能够识别日期字符串。如果我不能区分月份和日期(例如12/12/10),这并不重要,我只需要将字符串分类为日期,而不是将其转换为日期对象。因此,这实际上是一个分类问题,而不是解析问题 我将提供以下文本片段: “布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉 01/04/10bla bla bla bla” 我需要能够识别其中每个日期字符串的开始和结束边界 我想知道是否有人知道任何java库可以做到这一点。到目前为止,我的google fu还没有任何结果Java 识别任意日期字符串,java,date,classification,Java,Date,Classification,我需要能够识别日期字符串。如果我不能区分月份和日期(例如12/12/10),这并不重要,我只需要将字符串分类为日期,而不是将其转换为日期对象。因此,这实际上是一个分类问题,而不是解析问题 我将提供以下文本片段: “布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉 01/04/10bla bla bla bla” 我需要能够识别其中每个日期字符
更新:我需要能够识别最广泛的一套表示日期的方法。当然,最简单的解决方案可能是为每种可能的格式编写一个if语句,但理想情况下,我所追求的是一种带有经过训练的模型的模式识别方法。日期通常是由正斜杠或破折号分隔的字符。你考虑过正则表达式吗?< /P>
我假设你不想把日期分类为星期日、2010年10月3日等等,我不知道有哪家图书馆能做到这一点,但写你自己的并不难。假设您的日期都是用斜杠格式化的,比如
12/12/12
,那么您可以验证您有三个'\'。你可以更技术化,让它检查斜杠之间的值。例如,如果您有:
2010年12月30日
然后你知道30是天,12是月。然而,如果你得到30/30/10,你知道即使ti有正确的格式,它也不能是日期,因为没有“30”个月。也许你应该使用正则表达式 希望此版本适用于mm dd yyyy格式:
^(0[1-9]| 1[012])[-/.](0[1-9]|[12][0-9]|3[01])[-/.](19 | 20)\d$
这里的(0[1-9]| 1[012])
匹配00..12月份,(0[1-9]|[12][0-9]|[3[01])
匹配00..31日期,(19 | 20)\d\d
匹配一年
字段可以用破折号、斜线或圆点进行斜线
问候,,
谢尔盖我也不知道有哪家图书馆能做到这一点。我建议混合使用嵌套递归函数和正则表达式(很多)来匹配字符串,并尝试给出一个最佳猜测,看看它是否可以是一个日期。日期可以用很多不同的方式书写,有些人可能会用“2010年10月3日,星期日”或“2010年10月3日,星期日”或“2010年3月10日”或“2010年3月10日”等一系列不同的方式书写(如果你考虑使用其他语言/文化的日期,情况会更糟).您可以随时检查字符串中是否有两个“/”字符
public static boolean isDate(){
String date = "12/25/2010";
int counter = 0;
for(int i=0; i<date.length(); i++){
if ("\/-.".indexOf(date.charAt(i)) != -1) //Any symbol can be used.
counter++;
}
if(counter == 2) //If there are two symbols in the string,
return true; //Return true.
else
return false;
}
publicstaticbooleanisdate(){
字符串日期=“12/25/2010”;
int计数器=0;
对于(inti=0;i来说,实际上不可能使用“标准”算法将所有可能的日期格式识别为日期。这只是因为它们太多了
我们人类之所以能够做到这一点,仅仅是因为我们知道2010-03-31类似于日期。换句话说,我建议使用机器学习算法,教你的程序识别有效的日期序列。这样做应该是可行的
或者你可以像上面建议的那样使用正则表达式,来检测一些但不是所有的日期格式。我相信美国的研究人员已经研究过这个问题,但我找不到一篇论文
你可以尝试的一件事是把它作为一个两步的过程在收集尽可能多的数据后,提取特征、脑海中浮现的一些特征:字符串中出现的数字数量、字符串中出现的1-31之间的数字数量、字符串中出现的1-12之间的数字数量、字符串中出现的月份名称数量,等等使用某种类型的二进制分类方法(例如SVM)从特征中学习,最后(3)当出现新字符串时,提取特征并查询SVM进行预测。您可以在Java中循环所有可用的日期格式:
for (Locale locale : DateFormat.getAvailableLocales()) {
for (int style = DateFormat.FULL; style <= DateFormat.SHORT; style ++) {
DateFormat df = DateFormat.getDateInstance(style, locale);
try {
df.parse(dateString);
// either return "true", or return the Date obtained Date object
} catch (ParseException ex) {
continue; // unperasable, try the next one
}
}
}
(区域设置:DateFormat.getAvailableLocales())的{
对于(int style=DateFormat.FULL;style我使用了一个巨大的正则表达式(自创):
这与以下日期相符:
06 Sep 2010
12-5-2005
07 Mar 95
30 DEC '99
11\9\2001
而不是这个:
444/11/11
bla11/11/11
11/11/11blah
它还匹配符号之间的日期,如[]
,()
,,
:
Yesterday (6 nov 2010)
它匹配不带年份的日期:
Yesterday, 6 nov, was a rainy day...
但它与匹配:
86-44/1234
00-00-0000
11\11/11
这看起来不再像是一个日期了。但是你可以通过检查数字是否是一个月、一天、一年的可能值来解决这个问题。使用
您可能想使用from edu.mit.broad.genome.utils包。我要做的是查找日期特征,而不是日期本身。例如,您可以搜索斜杠(以获取格式1/1/1001的日期)、破折号(1-1-1001)、月份名称和缩写(1001年1月1日或1001年1月1日).当你找到这些单词时,收集附近的单词(每边2个就可以了)并将其存储在字符串数组中。扫描完所有输入后,使用一个函数检查此字符串数组,该函数将更深入,并使用此处找到的方法提取实际日期字符串。重要的是将一般日期降低到可管理的水平。可能有助于您完成任务的规则:
使用与月份匹配的已知单词创建或查找某种数据库。缩写和全名,如Jan
或janur
。在搜索时,它必须不区分大小写,因为二月也是一个月,尽管键入它的人一定喝醉了。如果您计划搜索非英语月份,还需要一个数据库ed,因为没有启发式方法会发现“Wrzesień”是9月份的波兰语
仅限英语,请查看并为数字1到31.T创建一个数据库
86-44/1234
00-00-0000
11\11/11
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
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.util.Locale;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
// DateTimeFormatter parser = DateTimeFormatter.ofPattern("[M/d/uu[ H:m]][d MMM u][M.d.u][E MMM d, u]", Locale.ENGLISH);
final DateTimeFormatter parser = new DateTimeFormatterBuilder()
.parseCaseInsensitive() // parse in case-insensitive manner
.appendPattern("[M/d/uu[ H:m]][d MMM u][M.d.u][E MMM d, u]")
.toFormatter(Locale.ENGLISH);
// Test
Stream.of(
"Thu Apr 1, 2021",
"THU Apr 1, 2021",
"01/06/10",
"1 Jan 2009",
"1.2.2010",
"asdf"
).forEach(s -> {
try {
LocalDate.parse(s, parser);
System.out.println(true);
} catch(DateTimeParseException e) {
System.out.println(false);
}
});
}
}
true
true
true
true
true
false