Java - 使用正则表达式从字符串中提取日期- 失败

9

我正在尝试使用正则表达式从一个字符串中提取2个日期,但出现了问题-正则表达式无法提取日期-以下是我的代码:

private  String[] getDate(String desc) {
    int count=0;
    String[] allMatches = new String[2];
    Matcher m = Pattern.compile("(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\\d\\d(?:,)").matcher(desc);
    while (m.find()) {
        allMatches[count] = m.group();
    }
    return allMatches;
}

我的字符串描述是:"从2009年11月25日到2009年11月30日",但我收到了一个空数组...


3
您的正则表达式适用于格式为“dd-MM-yyyy”的日期,但是字符串中的格式为“MM-dd-yyyy”。解决方案:您需要在所有地方使用一致的日期格式,但这在用户输入中并不总是可能的。您不能接受两种格式,因为您无法确定“01-02-2013”代表什么意思... - Kobi
+1 Kobi. 你也不要忘记递增 count - Arnaud Denoyelle
5个回答

14

你的正则表达式匹配日期以天为先,然后是月份 (DD/MM/YYYY),而你的输入是以月份为先,然后才是天数 (MM/DD/YYYY)。

此外,你的日期必须后面跟着逗号才能匹配 (即(?:,)部分)。

以下正则表达式应该符合你的需求:

(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d

正则表达式可视化

图示由Debuggex提供。


7

3个问题:

1)您正在尝试解析日期格式为dd/MM/YYYY,但您的正则表达式格式为MM/dd/YYYY

2)您在while循环中忘记增加count

3)正则表达式末尾的(?:,)部分是无用的。

这段代码在我的电脑上运行正常:

private static String[] getDate(String desc) {
  int count=0;
  String[] allMatches = new String[2];
  Matcher m = Pattern.compile("(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\\d\\d").matcher(desc);
  while (m.find()) {
    allMatches[count] = m.group();
    count++;
  }
  return allMatches;
}

测试

public static void main(String[] args) throws Exception{
  String[] dates = getDate("coming from the 25/11/2009 to the 30/11/2009");

  System.out.println(dates[0]);
  System.out.println(dates[1]);

}

输出

25/11/2009
30/11/2009

你可以在https://www.debuggex.com/r/VPIR1fOPhqZ_NIo1#cheatsheet中构建正则表达式。 - Doberon

5
你把月份和日期搞反了,(?:,) 要求每个日期末尾都有逗号。可以试试这个方法:

(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\\d\\d

0

一个日期模式识别算法,不仅可以识别日期模式,还可以以Java日期格式获取可能的日期。该算法非常快速和轻量级。处理时间是线性的,并且所有日期都在单次遍历中被识别。算法使用树遍历机制解析日期。树数据结构是自定义创建的,用于构建支持的日期、时间和月份模式。

该算法还承认日期文字之间的多个空格字符。例如,DD DD DD 和 DD DD DD 被视为有效日期。

以下日期模式被视为有效,并且可以使用此算法进行识别。

dd MM(MM) yy(yy) yy(yy) MM(MM) dd MM(MM) dd yy(yy)

其中 M 是月份文字,以字母格式表示,如 Jan 或 January

允许在日期之间使用的分隔符包括'/'、'\'、' '、','、'|'、'-'、' '

它还可以识别以下格式的尾随时间模式 hh(24):mm:ss.SSS am / pm hh(24):mm:ss am / pm hh(24):mm:ss am / pm

分辨率时间是线性的,不使用模式匹配或蛮力。该算法基于树遍历,并返回以下三个组件的日期列表 - 在文本中识别的日期字符串 - 转换和格式化的日期字符串 - SimpleDateFormat

使用日期字符串和格式字符串,用户可以根据自己的需求将字符串转换为对象。

算法库可在Maven中央获取。

<dependency>
    <groupId>net.rationalminds</groupId>
    <artifactId>DateParser</artifactId>
    <version>0.3.0</version>
</dependency>

以下是使用此代码的示例。
import java.util.List;  
 import net.rationalminds.LocalDateModel;  
 import net.rationalminds.Parser;  
 public class Test {  
   public static void main(String[] args) throws Exception {  
        Parser parser=new Parser();  
        List<LocalDateModel> dates=parser.parse("Identified date :'2015-January-10 18:00:01.704', converted");  
        System.out.println(dates);  
   }  
 }  

输出:[LocalDateModel {originalText = 2015年1月10日18:00:01.704,dateTimeString = 2015-1-10 18:00:01.704,conDateFormat = yyyy-MM-dd HH:mm:ss.SSS,start = 18,end = 46}]

详细博客请参见http://coffeefromme.blogspot.com/2015/10/how-to-extract-date-object-from-given.html

完整源代码可在GitHub上找到https://github.com/vbhavsingh/DateParser


你好,欢迎来到SO!我认为你的帖子中丢失了一些格式,因为第二段中的示例“DD DD DD”和“DD DD DD”看起来是相同的。也许使用更多的 code 标记来保留空格和显示格式? - thinkOfaNumber
它可能是“DD DD DDDD”、“DDDD DD DD”或“DD DD DD”。 - vaibhav singh

0

LocalTime.parse 替代正则表达式

对于这样的问题,正则表达式可能会过度使用。

您可以仅在空格字符上拆分字符串,并尝试将每个元素解析为 LocalDate。如果解析失败,请继续下一个元素。

String input = "coming from the 11/25/2009 to the 11/30/2009" ;
String[] elements = input.split( " " ) ; 
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu" ) ;
List<LocalDate> dates = new ArrayList<>() ;
for( String element : elements ) {
    try {
        LocalDate ld = LocalDate.parse( element , f ) ;
        dates.add( ld ) ;
    } catch ( DateTimeParseException e ) {
        // Ignore the exception. Move on to next element.
    }
}
System.out.println( "dates: " + dates ) ;

请查看在IdeOne.com上运行的代码

日期:[2009年11月25日,2009年11月30日]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接