Java 8 DateTimeFormatterBuilder (). AppendOptional not working

My requirement is to verify that the date string is in the correct format based on the set of valid formats.

Valid formats:

MM/dd/yy
MM/dd/yyyy

I created a simple testing method that uses Java 8 DateTimeFormatterBuilder to create flexible formatting that supports several optional formats. Here is the code:

public static void test() {
    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
            .appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
            .toFormatter();

    String dateString = "10/30/2017";

    try {
        LocalDate.parse(dateString, formatter);
        System.out.println(dateString + " has a valid date format");
    } catch (Exception e) {
        System.out.println(dateString + " has an invalid date format");
    }
}

When I ran this, here is the output

10/30/2017 has an invalid date format

As you can see in the code, valid date formats are MM / dd / yy and MM / dd / yyyy. I expected the date 10/30/2017 to be valid, as it corresponds to MM / dd / yyyy. However, 10/30/2017 is reported as invalid.

What is going wrong? Why is this not working?

I also tried

.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy[yy]"))

instead

.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))

but still has the same problem.

This code works as expected if I use:

String dateString = "10/30/17";

instead

String dateString = "10/30/2017";

I have 2 questions

  • ? "10/30/2017"?

  • Java 8, (, )? [] . - , ( [] )

+4
2

, ,

  • , (, "MM/dd/yy" ), ,
  • - , (, "MM/dd/yyyy" )

, , :

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
            .appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
            .toFormatter();

    String[] dateStrings = {
            "10/30/17",           // valid
            "10/30/2017",         // invalid
            "10/30/1710/30/2017", // valid
            "10/30/201710/30/17"  // invalid
    };

    for (String dateString : dateStrings) {
        try {
            LocalDate.parse(dateString, formatter);
            System.out.println(dateString + " has a valid date format");
        } catch (Exception e) {
            System.err.println(dateString + " has an invalid date format");
        }
    }

==

10/30/17 has a valid date format
10/30/1710/30/2017 has a valid date format
10/30/2017 has an invalid date format
10/30/201710/30/17 has an invalid date format

==

, , ,

  • ,
  • , ..

    String[] patterns = { "MM/dd/yy", "MM/dd/yyyy" };
    Map<String, DateTimeFormatter> formatters = Stream.of(patterns).collect(Collectors.toMap(
            pattern -> pattern, 
            pattern -> new DateTimeFormatterBuilder().appendOptional(DateTimeFormatter.ofPattern(pattern)).toFormatter()
    ));
    
    String dateString = "10/30/17";
    boolean valid = formatters.entrySet().stream().anyMatch(entry -> {
        // relying on catching parsing exception will have serious expense on performance
        // a simple check will already improve a lot 
        if (dateString.length() == entry.getKey().length()) {
            try {
                LocalDate.parse(dateString, entry.getValue());
                return true;
            }
            catch (DateTimeParseException e) {
                // ignore or log it   
            }
        }
        return false;
    });
    
+3

appendValueReduced() .

.

. , , 1970 2069 , 1970 . :

    LocalDate century = LocalDate.ofEpochDay(0); /* Beginning Jan. 1, 1970 */
    DateTimeFormatter f = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ofPattern("MM/dd/"))
            .appendValueReduced(ChronoField.YEAR, 2, 4, century)
            .toFormatter();
    System.out.println(LocalDate.parse("10/30/2017", f)); /* 2017-10-30 */
    System.out.println(LocalDate.parse("10/30/17", f));   /* 2017-10-30 */
    System.out.println(LocalDate.parse("12/28/1969", f)); /* 1969-12-28 */
    System.out.println(LocalDate.parse("12/28/69", f));   /* 2069-12-28 */
0

Source: https://habr.com/ru/post/1691433/


All Articles