首页 > 解决方案 > Java 8 Vavr onFailure 连接

问题描述

我试图解析一个包含未知格式日期的字符串,而我选择的方式(不是最好的)是尝试所有可能的格式,直到正确解析。为此,我使用 Vavr 库,直到现在我已经创建了这样的东西:

// My unknown date
    String date = "2020-11-12T15:15:15.345";


    // Date format that works for my unknown date (just for testing)
    DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
            .appendPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]")
            .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
            .toFormatter();
    OffsetDateTime value = OffsetDateTime.parse(date, FORMATTER);                   // PARSE CORRECTLY 


// Try all possible formats until one works
    Try<OffsetDateTime> myParsedDate = Try.of(()->date)
            .map(x->OffsetDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")))
            .onFailure(x->System.out.println("NO yyyy-MM-dd"))

            .map(x->OffsetDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS+HH:mm")))
            .onFailure(x->System.out.println("NO yyyy-MM-dd'T'HH:mm:ss.SSS+HH:mm"))

            .map(x->OffsetDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS+HH:mm")))
            .onFailure(x->System.out.println("NO yyyy-MM-dd'T'HH:mm:ss.SSS+HH:mm"))

            .map(x->OffsetDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")))
            .onFailure(x->System.out.println("NO yyyy-MM-dd'T'HH:mm:ss.SSS"))

            .map(x->OffsetDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")))
            .onFailure(x->System.out.println("NO yyyy-MM-dd'T'HH:mm:ss.SSSZ"))

            .map(x->OffsetDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")))
            .onFailure(x->System.out.println("NO yyyy-MM-dd'T'HH:mm:ss"))

            .map(x->OffsetDateTime.parse(date, FORMATTER))                          // DOSENT WORK
            .onFailure(x->System.out.println("NO yyyy-MM-dd'T'HH:mm:ss[.SSS]"));
    if(myParsedDate.isSuccess()) {
        System.out.println("OK");
    }else {
        System.out.println("KO");
    }

输出:

NO yyyy-MM-dd
NO yyyy-MM-dd'T'HH:mm:ss.SSS+HH:mm
NO yyyy-MM-dd'T'HH:mm:ss.SSS+HH:mm
NO yyyy-MM-dd'T'HH:mm:ss.SSS
NO yyyy-MM-dd'T'HH:mm:ss.SSSZ
NO yyyy-MM-dd'T'HH:mm:ss
NO yyyy-MM-dd'T'HH:mm:ss[.SSS]

问题是:如何连接许多 try/catch 或者在这种情况下使用 VAVR 许多动作,当一个动作失败时尝试下一个动作等等?谢谢

标签: datetimejava-8java-timedatetime-parsingvavr

解决方案


用 vavr 回答

import io.vavr.collection.Iterator;

String[] patterns = new String[] {
   "yyyy-MM-dd",
   "yyyy-MM-dd'T'HH:mm:ss.SSS+HH:mm",
   "yyyy-MM-dd'T'HH:mm:ss.SSS",
   "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
   "yyyy-MM-dd'T'HH:mm:ss"
};

final Option<OffsetDateTime> offsetDateTimeOption =
   Iterator.of(patterns)                                                     // 1
      .map(DateTimeFormatter::ofPattern)                                     // 2
      .concat(Iterator.of(FORMATTER))                                        // 3
      .map(formatter -> Try.of(() -> OffsetDateTime.parse(date, formatter))) // 4
      .flatMap(Try::iterator)                                                // 5
      .headOption();                                                         // 6

脚步

  1. Iterator从对模式数组的惰性开始
  2. 转换为格式化程序
  3. 将后备格式化程序附加到Iterator
  4. 使用格式化程序解析日期,将结果包装在Try
  5. 通过Iterator<Try<OffsetDateTime>>Iterator<OffsetDateTime>每个Try. try 上的迭代器如果成功则为单元素迭代器,如果失败则为空迭代器
  6. 获取结果迭代器的第一个元素,Some如果它不为空,则将其作为 a 返回或返回 aNone

上面的管道是惰性的,也就是说,它只尝试尽可能多的模式/格式化程序来找到第一个成功的,因为 vavrIterator本身就是惰性的。

我的回答只关注如何在vavr首次成功之前进行惰性评估,我没有尝试纠正您的问题的其他方面,这些方面会导致您的模式与显然符合其中一些模式的日期字符串不匹配。您的问题的其他答案详细介绍了我不想在这里重复的内容。


推荐阅读