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

我的程序正在将输入字符串解析为 LocalDate 对象。在大多数情况下,字符串看起来像 ,但偶尔看起来像 。根据具体情况,我需要使用不同的模式进行调用。基本上,我需要检查字符串是否与模式匹配或在进行解析之前检查。30.03.20143/30/2014DateTimeFormatter.ofPattern(String pattern)dd.MM.yyyyM/dd/yyyy

正则表达式方法将如下所示:

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"));  
}

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

是否有任何标准方法可以使用新的Java 8时间API来执行此操作,而无需诉诸正则表达式匹配?我已经在文档中查找了DateTimeFormatter,但我找不到任何东西。


答案 1

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

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");
    }
}

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


另一种方法是使用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

答案 2

使用 DateTimeFormatter,可以使用方括号指定可选模式。

演示:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("[d.M.u][M/d/u][u-M-d]", Locale.ENGLISH);
        Stream.of(
                    "3/30/2014",
                    "30.03.2014",
                    "2014-05-14",
                    "14.05.2014"
        ).forEach(s -> System.out.println(LocalDate.parse(s, dtf)));
    }
}

输出:

2014-03-30
2014-03-30
2014-05-14
2014-05-14

了解有关现代日期时间 API*的更多信息,请参阅跟踪:日期时间


*出于任何原因,如果你必须坚持使用Java 6或Java 7,你可以使用ThreeTen-Backport,它将大部分java.time功能反向移植到Java 6和7。如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请查看通过desugaring提供的Java 8 +API如何在Android项目中使用ThreeTenABP