DateTimeFormatter接受多个日期并转换为一个日期(java.time库)

Ale*_*ser 7 java datetime datetime-format datetime-parsing java-time

我正在尝试编写一个DateTimeFormatter允许我采用多种不同String格式的格式,然后将String格式转换为特定类型.由于项目的范围和已经存在的代码,我不能使用不同类型的格式化程序.

例如,我想接受MM/dd/yyyy以及yyyy-MM-dd'T'HH:mm:ss然后当我打印时我只想打印MM/dd/yyyy格式并在我打电话时将其格式化LocalDate.format(formatter);

有人可以建议如何用这个做到这一点 java.time.format.*;

以下是我可以做到的方式org.joda:

// MM/dd/yyyy format
DateTimeFormatter monthDayYear = DateTimeFormat.forPattern("MM/dd/yyyy");
// array of parsers, with all possible input patterns
DateTimeParser[] parsers = {
        // parser for MM/dd/yyyy format
        monthDayYear.getParser(),
        // parser for yyyy-MM-dd'T'HH:mm:ss format
        DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss").getParser()
};
DateTimeFormatter parser = new DateTimeFormatterBuilder()
    // use the monthDayYear formatter for output (monthDayYear.getPrinter())
    // and parsers array for input (parsers)
    .append(monthDayYear.getPrinter(), parsers)
    // create formatter (using UTC to avoid DST problems)
    .toFormatter()
    .withZone(DateTimeZone.UTC);
Run Code Online (Sandbox Code Playgroud)

我还没有在网上找到一个好的/有效的例子.

小智 11

我已经使用JDK 1.8.0_131(适用于Mac OS X)JDK 1.8.0111(适用于Windows)(均可使用)进行了测试.

我创建了一个DateTimeFormatter带有可选部分(由分隔符[])来解析两个案例(MM/dd/yyyyyyyy-MM-dd'T'HH:mm:ss).

相同的格式化程序适用于您的case(LocalDate),但下面有一些注意事项.

// parse both formats (use optional section, delimited by [])
DateTimeFormatter parser = DateTimeFormatter.ofPattern("[MM/dd/yyyy][yyyy-MM-dd'T'HH:mm:ss]");

// parse MM/dd/yyyy
LocalDate d1 = LocalDate.parse("10/16/2016", parser);
// parse yyyy-MM-dd'T'HH:mm:ss
LocalDate d2 = LocalDate.parse("2016-10-16T10:20:30", parser);

// parser.format(d1) is the same as d1.format(parser)
System.out.println(parser.format(d1));
System.out.println(parser.format(d2));
Run Code Online (Sandbox Code Playgroud)

输出是:

2016/10/16
2016/10/16


PS:这只适用于LocalDate.如果我尝试使用时间字段(如LocalDateTime)格式化对象,则使用两种格式:

System.out.println(parser.format(LocalDateTime.now()));
Run Code Online (Sandbox Code Playgroud)

这打印:

6月18日/ 20172017-06-18T07:40:55

请注意,它使用两种模式格式化.我猜测格式化程序会检查对象是否包含每个可选节中的字段.由于LocalDate没有时间字段(小时/分钟/秒),第二个模式失败,它只打印第一个(MM/dd/yyyy).但是它LocalDateTime具有所有时间字段,并且两种模式都是有效的,因此两者都用于格式化.

我的结论是:这不是一般解决方案(如Joda-Time的版本),它更像是一个"幸运"案例,其中涉及的模式创造了所需的情况.但我不会依赖于所有情况.

无论如何,如果您只是使用LocalDate,您可以尝试使用此代码.但是如果你正在使用其他类型,那么你可能不得不使用另一个格式化器来输出,如下所示:

// parser/formatter for month/day/year
DateTimeFormatter mdy = DateTimeFormatter.ofPattern("MM/dd/yyyy");
// parser for both patterns
DateTimeFormatter parser = new DateTimeFormatterBuilder()
    // optional MM/dd/yyyy
    .appendOptional(mdy)
    // optional yyyy-MM-dd'T'HH:mm:ss (use built-in formatter)
    .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
    // create formatter
    .toFormatter();

// parse MM/dd/yyyy
LocalDate d1 = LocalDate.parse("10/16/2016", parser);
// parse yyyy-MM-dd'T'HH:mm:ss
LocalDate d2 = LocalDate.parse("2016-10-16T10:20:30", parser);

// use mdy to format
System.out.println(mdy.format(d1));
System.out.println(mdy.format(d2));

// format object with time fields: using mdy formatter to avoid multiple pattern problem
System.out.println(mdy.format(LocalDateTime.now()));
Run Code Online (Sandbox Code Playgroud)

输出是:

10/16/2016
10/16/2016
06/18/2017