【问题标题】:String Regex in Java - Puzzle [closed]Java中的字符串正则表达式 - 拼图[关闭]
【发布时间】:2014-07-30 15:18:13
【问题描述】:

我有以下包含多个日期的字符串;像这样:

I was born on 8/11/1965.我需要将所有日期更改为不同的格式。

实现这一目标的最佳优化方法是什么?

注意:

我没有要求别人给我密码;只征求建议;因此看不到任何负面评价的原因。

【问题讨论】:

  • 你猜错了,使用日期解析模块。
  • 如果日期的格式未知,这将是不可能的。你打算用 12/12/12 做什么?使用正则表达式获取典型格式的日期,并使用日期格式化程序解析和格式化它们是可能的。
  • @user182944 我认为反对票是因为没有显示您的尝试,也没有完成您的问题,以使其成为对未来读者有帮助的问题。
  • 在 StackOverflow 中搜索“java 日期格式”会返回数千个匹配项;也许是反对票的原因。无论如何,请阅读我在上述评论中发布的重复问题的答案。关注Joda-Timejava.time,因为旧的 java.util.Date 和 .Calendar 类对你的心理健康有害。几乎不需要正则表达式,因为这两个出色的日期时间库可以为您完成繁重的工作。
  • 正则表达式仅用于从文本中提取日期,并用格式化的日期替换它们。 Joda-Time 和 java.time 不会为您解析英文句子中的日期,也不会进行替换。

标签: java regex data-structures


【解决方案1】:

这是完整的算法。

Pattern ddpat = Pattern.compile( "\\d{1,2}/\\d{1,2}/\\d{4}" );
DateFormat dddf = new SimpleDateFormat("dd/MM/yyyy");
DateFormat wwdf = new SimpleDateFormat("EEEE, MMMM d yyyy");
String s = "I was born on 18/11/1965. and completed my grad on 9/10/1978 and so on";
StringBuilder sb = new StringBuilder();
Matcher ddmat = ddpat.matcher( s );
int offset = 0;
while( ddmat.find( offset ) ){
    int beg = ddmat.start();
    int end = ddmat.end();
    String dd = s.substring( beg, end );
    String ww = wwdf.format( dddf.parse( dd ) );
    sb.append( s.substring( offset, beg ) ).append( ww );
    offset = end;
}
sb.append( s.substring( offset ) );
System.out.println( sb.toString() );

要处理 99/99/9999 和类似情况,请在 dddf.parse( dd ) 之后处理 ParseException 并替换为您认为合适的任何内容。不匹配正则表达式的字符串是没有希望的,除非你能想到一个匹配“错误日期”的正则表达式。 ;-)

稍后

如果你想钓几种格式:

Pattern ddpat = Pattern.compile( "(\\d{1,2}/\\d{1,2}/\\d{4})|(\\d{4}-\\d{2}-\\d{2})" );
DateFormat[] dddf = new DateFormat[]{
    new SimpleDateFormat("dd/MM/yyyy"),
    new SimpleDateFormat("yyyy-MM-dd") };
DateFormat wwdf = new SimpleDateFormat("EEEE, MMMM d yyyy");
String s = "I was born on 18/11/1965. and completed my grad on 1978-10-09 and so on";
StringBuilder sb = new StringBuilder();
Matcher ddmat = ddpat.matcher( s );
int offset = 0;
while( ddmat.find( offset ) ){
    for( int ig = 1; ig <= ddmat.groupCount(); ig++ ){
    if( ddmat.group(ig) != null ){
        int beg = ddmat.start(ig);
        int end = ddmat.end(ig);
        String dd = s.substring( beg, end );
        String ww = wwdf.format( dddf[ig-1].parse( dd ) );
        sb.append( s.substring( offset, beg ) ).append( ww );
        offset = end;
        break;
    }
    }
}
sb.append( s.substring( offset ) );
System.out.println( sb.toString() );

【讨论】:

  • 我只看到我使用了“d”而不是“dd”。这是因为我在口头日期“官僚风格”中发现月份中的前导零。 YMMV。
  • 感谢您的示例代码。我计划在正则表达式中使用 OR 即| 和一系列日期模式。这是个好主意吗?请问有什么帮助吗?
  • @user182944 不是“||”,但您可以使用“|”。您将不得不尝试使用多种 DateFormat 进行转换。使用单个组可能会告诉您格式,然后您就知道 DateFormat。
  • 不,知道日期格式是不可能的,因此试图找出不同的选项。除了使用 | 之外,您能否提出其他选择?
  • @user182944 下定决心!您要么知道许多可能的格式,要么不知道。如果您知道正则表达式模式,您就会知道日期格式。 -- 查看更新后的答案。
【解决方案2】:

如果我理解您的目标,我能想到的最简单的方法是使用两个 SimpleDateFormat 实例。一种用于您的输入格式,一种用于您的输出格式。也就是说,像 -

String str = "8/11/1965";
DateFormat in = new SimpleDateFormat("dd/MM/yyyy");
DateFormat out = new SimpleDateFormat("EEEE, MMMM dd yyyy");
System.out.println(out.format(in.parse(str)));

输出是(因为 1965 年 11 月 8 日是星期一而不是星期三)-

Monday, November 08 1965

$ cal 11 1965
   November 1965      
Su Mo Tu We Th Fr Sa  
    1  2  3  4  5  6  
 7  8  9 10 11 12 13  
14 15 16 17 18 19 20  
21 22 23 24 25 26 27  
28 29 30              

【讨论】:

  • 感谢您的回复。格式化部分对我来说很好,导致问题的部分是String 中包含不同种类的日期格式。如何处理?请建议
  • laune 已经回答了here。在识别多种格式的日期方面,您的问题仍然不清楚......这是一个模棱两可的努力。
猜你喜欢
  • 1970-01-01
  • 2015-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
相关资源
最近更新 更多