Java 如何使用时间 API 检查字符串是否与日期模式匹配?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23488721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 23:21:29  来源:igfitidea点击:

How to check if string matches date pattern using time API?

javajava-8datetime-formatdatetime-parsingjava-time

提问by

My program is parsing an input string to a LocalDateobject. For most of the time the string looks like 30.03.2014, but occasionally it looks like 3/30/2014. Depending on which, I need to use a different pattern to call DateTimeFormatter.ofPattern(String pattern)with. Basically, I need to check if the string matches the pattern dd.MM.yyyyor M/dd/yyyybefore doing the parsing.

我的程序正在将输入字符串解析为LocalDate对象。大多数时候字符串看起来像30.03.2014,但偶尔看起来像3/30/2014。根据哪个,我需要使用不同的模式来调用DateTimeFormatter.ofPattern(String pattern)。基本上,我需要检查,如果字符串匹配的模式dd.MM.yyyyM/dd/yyyy做分析之前。

The regex approach would be something like:

正则表达式方法类似于:

LocalDate date;
if (dateString.matches("^\d?\d/\d{2}/\d{4}$")) {
  date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("M/dd/yyyy"));  
} else {
  date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("dd.MM.yyyy"));  
}

This works, but it would be nice to use the date pattern string when matching the string also.

这有效,但在匹配字符串时也使用日期模式字符串会很好。

Are there any standard ways to do this with the new Java 8 time API, without resorting to regex matching? I have looked in the docs for DateTimeFormatterbut I couldn't find anything.

是否有任何标准方法可以使用新的 Java 8 时间 API 执行此操作,而无需求助于正则表达式匹配?我查看了文档,DateTimeFormatter但找不到任何内容。

采纳答案by Alexis C.

Okay I'm going ahead and posting it as an answer. One way is to create the class that will holds the patterns.

好的,我将继续并将其发布为答案。一种方法是创建将保存模式的类。

public class Test {
    public static void main(String[] args){
        MyFormatter format = new MyFormatter("dd.MM.yyyy", "M/dd/yyyy");
        LocalDate  date = format.parse("3/30/2014"); //2014-03-30
        LocalDate  date2 = format.parse("30.03.2014"); //2014-03-30
    }
}

class MyFormatter {
    private final String[] patterns;

    public MyFormatter(String... patterns){
        this.patterns = patterns;
    }

    public LocalDate parse(String text){
        for(int i = 0; i < patterns.length; i++){
            try{
                return LocalDate.parse(text, DateTimeFormatter.ofPattern(patterns[i]));
            }catch(DateTimeParseException excep){}
        }
        throw new IllegalArgumentException("Not able to parse the date for all patterns given");
    }
}

You could improve this as @MenoHochschild did by directly creating an array of DateTimeFormatterfrom the array of Stringyou pass in the constructor.

您可以像@MenoHochschild 那样通过直接DateTimeFormatterString构造函数中传递的数组中创建一个数组来改进这一点。



Another way would be to use a DateTimeFormatterBuilder, appending the formats you want. There may exists some other ways to do it, I didn't go deeply through the documentation :-)

另一种方法是使用 a DateTimeFormatterBuilder,附加您想要的格式。可能还有其他一些方法可以做到这一点,我没有深入阅读文档:-)

DateTimeFormatter dfs = new DateTimeFormatterBuilder()
                           .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd"))                                                                 
                           .appendOptional(DateTimeFormatter.ofPattern("dd.MM.yyyy"))                                                                                     
                           .toFormatter();
LocalDate d = LocalDate.parse("2014-05-14", dfs); //2014-05-14
LocalDate d2 = LocalDate.parse("14.05.2014", dfs); //2014-05-14

回答by Meno Hochschild

The approach of @ZouZou is a possible solution.

@ZouZou 的方法是一个可能的解决方案。

In order to avoid using exceptions for program logic as much as possible (also not so nice performancewise) following alternativemight be considered:

为了尽可能避免对程序逻辑使用异常(在性能方面也不太好),可以考虑以下替代方案

static final String[] PATTERNS = {"dd.MM.yyyy", "M/dd/yyyy"};
static final DateTimeFormatter[] FORMATTERS = new DateTimeFormatter[PATTERNS.length];

static {
  for (int i = 0; i < PATTERNS.length; i++) {
    FORMATTERS[i] = DateTimeFormatter.ofPattern(PATTERNS[i]);
  }
}

public static LocalDate parse(String input) {
  ParsePosition pos = new ParsePosition();
  for (int i = 0; i < patterns.length; i++) {
    try {
      TemporalAccessor tacc = FORMATTERS[i].parseUnresolved(input, pos);
      if (pos.getErrorIndex < 0) {
        return LocalDate.from(tacc); // possibly throwing DateTimeException => validation failure
      }
    } catch (DateTimeException ex) { // catches also possible DateTimeParseException
      // go to next pattern
    }
    pos.setIndex(0);
    pos.setErrorIndex(-1);
  }
  throw new IllegalArgumentException("Input does not match any pattern: " + input);
}

More explanation about the method parseUnresolved():

关于该方法的更多解释parseUnresolved()

This method does only the first phase of parsing, so there is no second phase containing preliminary validation or combining effort of parsed fields. However, LocalDate.from()does validate every input, so I think this is still sufficient. And the advantage is that parseUnresolved()uses the error index of ParsePosition. This is in agreement with traditional java.text.Format-behaviour.

此方法仅执行解析的第一阶段,因此没有包含初步验证或解析字段的组合工作的第二阶段。但是,LocalDate.from()确实验证了每个输入,所以我认为这仍然足够了。优点是parseUnresolved()使用了 的错误索引ParsePosition。这与传统的java.text.Format行为一致。

Unfortunately the alternative and more intuitive method DateTimeFormater.parse()first creates a DateTimeParseExceptionand then store the error index in this exception. So I decided not to use this method in order to avoid the creation of an unnecessary exception. For me, this API-detail is a questionable design decision.

不幸的是,另一种更直观的方法DateTimeFormater.parse()首先创建一个DateTimeParseException,然后将错误索引存储在此异常中。所以我决定不使用这种方法,以避免产生不必要的异常。对我来说,这个 API 细节是一个有问题的设计决策。