【问题标题】:Extract multiple dates (dd-MMM-yyyy format) from a string in java从java中的字符串中提取多个日期(dd-MMM-yyyy格式)
【发布时间】:2019-07-02 08:30:24
【问题描述】:

我到处搜索,但找不到具体的解决方案,文档也没有涵盖这一点。所以我想从这个字符串"1-Mar-2019 to 31-Mar-2019" 中提取开始日期和结束日期。问题是我无法提取两个日期字符串。

我在这里找到了最接近的解决方案,但由于声誉低,无法发表评论询问如何单独提取值:https://stackoverflow.com/a/8116229/10735227

我正在使用正则表达式模式来查找出现并首先将两个出现提取到 2 个字符串。
这是我尝试过的:

Pattern p = Pattern.compile("(\\d{1,2}-[a-zA-Z]{3}-\\d{4})");  
Matcher m = p.matcher(str);
while(m.find())
{
    startdt = m.group(1); 
    enddt = m.group(1);   //I think this is wrong, don't know how to fix it
}
System.out.println("startdt: "+startdt+" enddt: "+enddt);

输出为:

startdt: 31-Mar-2019 enddt: 31-Mar-2019

此外,我需要使用 DateFormatter 将字符串转换为日期(如果需要,在单个数字日期之前添加尾随 0)。

【问题讨论】:

  • 实际上,您可以使用代码提取两个日期。在 while 块中需要两次迭代。您的意思是“一次”使用 1 个正则表达式获得两者?
  • @WiktorStribiżew 或者最好完全没有 while 循环。
  • 也许你可以做这样的事情 Pattern p = Pattern.compile("(\\d{1,2}-[a-zA-Z]{3}-\\d{4} ) 到 (\\d{1,2}-[a-zA-Z]{3}-\\d{4})");匹配器 m = p.matcher(str); while(m.find()) { startdt = m.group(1); enddt = m.group(2); }
  • @WiktorStribiżew 我的意思是将 2 个日期放入 2 个字符串中,无论是一次还是通过循环(如果需要)
  • 我认为s.split("\\s*to\\s*") 可以。

标签: java regex string date


【解决方案1】:

您只需调用find 方法两次即可捕获两个日期,如果您只有一个,则只会捕获第一个日期:

String str = "1-Mar-2019 to 31-Mar-2019";

String startdt = null, enddt = null;

Pattern p = Pattern.compile("(\\d{1,2}-[a-zA-Z]{3}-\\d{4})");  
Matcher m = p.matcher(str);
if(m.find()) {
    startdt = m.group(1); 
    if(m.find()) {
       enddt = m.group(1);
    }
}   
System.out.println("startdt: "+startdt+" enddt: "+enddt);

请注意,这可以与 while(m.find())List<String 一起使用,以便能够提取您可以找到的每个日期。

【讨论】:

  • 迄今为止最好的建议,恕我直言。您还可以使用更长的正则表达式,包括两个日期,并将 tham 捕获为第 1 组和第 2 组。
  • @OleV.V.这是我回答的第二部分,但Wiktor Stribiżew's answer 先发布;)
【解决方案2】:

如果您的文本可能很乱,并且您确实需要使用正则表达式来提取日期范围,您可以使用

String str = "Text here 1-Mar-2019 to 31-Mar-2019 and tex there";
String startdt = "";
String enddt = "";

String date_rx = "\\d{1,2}-[a-zA-Z]{3}-\\d{4}";
Pattern p = Pattern.compile("(" + date_rx + ")\\s*to\\s*(" + date_rx + ")");  
Matcher m = p.matcher(str);
if(m.find())
{
    startdt = m.group(1); 
    enddt = m.group(2); 
}
System.out.println("startdt: "+startdt+" enddt: "+enddt);
// => startdt: 1-Mar-2019 enddt: 31-Mar-2019

Java demo

另外,请考虑以下增强功能:将日期作为整个单词进行匹配,以避免较长字符串中的部分匹配:

Pattern.compile("\\b(" + date_rx + ")\\s*to\\s*(" + date_rx + ")\\b")

如果范围可以用-to 表示,您可以将to 替换为(?:to|-),甚至(?:to|\\p{Pd}),其中\p{Pd} 匹配任何 连字符/破折号。

【讨论】:

  • 我去了Pattern.compile(regexDate + ".*?" + regexDate);,但没有时间发布它!这将是在一个正则表达式中获取两个日期的最干净的方法
  • @AxelH 我不确定.*? 是否最好检测日期时间范围,通常用to 或破折号表示,所以我建议date_rx + \s*(?:to|\p{Pd})\s* + date_rx
  • 是的,我使用惰性量词只是为了保持示例的可读性。但我喜欢你没有在date_rx 中包含该组,它是可重复使用的!
【解决方案3】:

您可以简单地使用String::split

String range = "1-Mar-2019 to 31-Mar-2019";
String dts [] = range.split(" ");
System.out.println(dts[0]);
System.out.println(dts[2]);

【讨论】:

  • 谢谢,但我还是想知道如何通过正则表达式提取匹配项,因为字符串可能会改变(但仍然有日期)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-14
  • 2021-10-06
  • 2020-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多