Java 8 Date相当于具有多种解析器格式的Joda的DateTimeFormatterBuilder?

Tod*_*odd 21 java jodatime java-time

我目前有一个Joda日期解析器,它使用DateTimeFormatterBuilder,我可能会收到六种不同的日期格式.

我正在迁移到Java 8的Date例程,并没有看到等效的.

如何使用Java 8 Dates做这样的事情?

DateTimeParser[] parsers = { 
    DateTimeFormat.forPattern( "yyyy/MM/dd HH:mm:ss.SSSSSS" ).getParser() ,
    DateTimeFormat.forPattern( "yyyy-MM-dd HH:mm:ss" ).getParser() ,
    DateTimeFormat.forPattern( "ddMMMyyyy:HH:mm:ss.SSS Z" ).getParser() ,
    DateTimeFormat.forPattern( "ddMMMyyyy:HH:mm:ss.SSS" ).getParser() ,
    DateTimeFormat.forPattern( "ddMMMyyyy:HH:mm:ss.SSSSSS" ).getParser() ,
    DateTimeFormat.forPattern( "yyyy-MM-dd HH:mm:ss.SSS" ).getParser() 
};

DateTimeFormatter dateTimeFormatterInput = new DateTimeFormatterBuilder()
     .append( null, parsers ).toFormatter();
Run Code Online (Sandbox Code Playgroud)

Tun*_*aki 26

没有直接的工具可以做到这一点,但您可以使用可选部分.可选部分包含在方括号内[].这允许String的整个部分被解析为缺失.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(""
    + "[yyyy/MM/dd HH:mm:ss.SSSSSS]"
    + "[yyyy-MM-dd HH:mm:ss[.SSS]]"
    + "[ddMMMyyyy:HH:mm:ss.SSS[ Z]]"
);
Run Code Online (Sandbox Code Playgroud)

此格式化程序为您拥有的三种主要模式定义了3个可选的大部分.每个都在自己的可选部分内.

工作演示代码:

public static void main(String[] args) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(""
        + "[yyyy/MM/dd HH:mm:ss.SSSSSS]"
        + "[yyyy-MM-dd HH:mm:ss[.SSS]]"
        + "[ddMMMyyyy:HH:mm:ss.SSS[ Z]]"
    , Locale.ENGLISH);
    System.out.println(LocalDateTime.parse("2016/03/23 22:00:00.256145", formatter));
    System.out.println(LocalDateTime.parse("2016-03-23 22:00:00", formatter));
    System.out.println(LocalDateTime.parse("2016-03-23 22:00:00.123", formatter));
    System.out.println(LocalDateTime.parse("23Mar2016:22:00:00.123", formatter));
    System.out.println(LocalDateTime.parse("23Mar2016:22:00:00.123 -0800", formatter));
}
Run Code Online (Sandbox Code Playgroud)

  • 我应该指出的是,模式的顺序很重要,它们应该从最长到最短,从最严格到最不严格。这不起作用: `DateTimeFormatter formatter = DateTimeFormatter.ofPattern("" + "[yyyy-MM-dd]" + "[yyyy-MM-dd HH:mm:ss]" + "[dd/MM/yyyy]" + "[dd/MM/yyyy HH:mm:ss]")` 这是正确的: `DateTimeFormatter.ofPattern("" + "[yyyy-MM-dd HH:mm:ss]" + "[dd/MM/ yyyy HH:mm:ss]" + "[yyyy-MM-dd]" + "[dd/MM/yyyy]" )` (2认同)

小智 9

作为Tunaki的替代答案,您还可以使用DateTimeFormatterBuilder:

DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
  .appendPattern("[yyyy]")
  .appendPattern("[M/d/yyyy]")
  .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
  .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
  .toFormatter()
Run Code Online (Sandbox Code Playgroud)

  • @Avec try-catch 应该用于处理异常而不是用于预期的输入。但是您是对的,建议的代码不正确。只能通过 DateTimeFormatterBuilder 的 appendOptional-method 使用多个格式化程序。 (2认同)

Bri*_*ice 6

当代码需要以可配置的方式接受不同的模式时,使用流来迭代@Tinaki的解决方案:

DateTimeFormatter dateTimeFormatter = dateFormats.stream()
        .map(DateTimeFormatter::ofPattern)
        .reduce(new DateTimeFormatterBuilder(), 
                DateTimeFormatterBuilder::appendOptional, 
                (f1, f2) -> f1.append(f2.toFormatter()))
        .toFormatter();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我不关心减速器的组合器部分,但我需要它在签名中,所以我使组合器正确.

此代码将几乎等同于如果上述模式(yyyy/MM/dd HH:mm:ss.SSSSSS,yyyy-MM-dd HH:mm:ss[.SSS],ddMMMyyyy:HH:mm:ss.SSS[ Z])将被馈送到数据流:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendOptional(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSSSSS")
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]"
    .appendOptional(DateTimeFormatter.ofPattern("ddMMMyyyy:HH:mm:ss.SSS[ Z]")
    .toFormatter();
Run Code Online (Sandbox Code Playgroud)