DateTimeFormatter accepting multiple dates and converting to one (java.time library)

I am trying to write DateTimeFormatterwhich will allow me to accept several different formats Stringand then convert the formats Stringto a specific type. Due to the size of the project and the code that already exists, I cannot use another type of formatting.

For example, I want to accept MM/dd/yyyyas well yyyy-MM-dd'T'HH:mm:ss, but then when I print, I only need to print in the format MM/dd/yyyyand have it in the format when I callLocalDate.format(formatter);

Can anyone suggest ideas on how to do this with java.time.format.*;

Here is how I could do it in 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);

I have not found a good / working example of this online.

+4
4

JDK 1.8.0_131 Mac OS X JDK 1.8.0111 Windows ( ).

DateTimeFormatter ( []), (MM/dd/yyyy yyyy-MM-dd'T'HH:mm:ss).

(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));

:

10/16/2016
10/16/2016


PS: LocalDate. (, LocalDateTime), :

System.out.println(parser.format(LocalDateTime.now()));

:

06/18/20172017-06-18T07: 40: 55

, . , formatter , . 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()));

:

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

+3

- ​​ ThreeTen-Extra. . parseUnresolved(), , :

public static <T> T parseFirstMatching(CharSequence text, TemporalQuery<T> query, DateTimeFormatter... formatters) {
    Objects.requireNonNull(text, "text");
    Objects.requireNonNull(query, "query");
    Objects.requireNonNull(formatters, "formatters");
    if (formatters.length == 0) {
        throw new DateTimeParseException("No formatters specified", text, 0);
    }
    if (formatters.length == 1) {
        return formatters[0].parse(text, query);
    }
    for (DateTimeFormatter formatter : formatters) {
        try {
            ParsePosition pp = new ParsePosition(0);
            formatter.parseUnresolved(text, pp);
            int len = text.length();
            if (pp.getErrorIndex() == -1 && pp.getIndex() == len) {
                return formatter.parse(text, query);
            }
        } catch (RuntimeException ex) {
            // should not happen, but ignore if it does
        }
    }
    throw new DateTimeParseException("Text '" + text + "' could not be parsed", text, 0);
}

, DateTimeFormatter, Joda-Time.

+2

, , .

DateTimeFormatter - final, .

, . DateTimeFormatter - DateTimeFormatterBuilder. , static DateTimeFormatter DateTimeFormatterBuilder, .

public static DateTimeFormatter ofPattern(String pattern) {
    return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
}

DateTimeFormatterBuilder final , - , .

, DateTimeFormatter . DateTimeFormatter, .

+1

The answer from Andreas is correct and should be accepted.

Check string length

Alternatively, you can simply check the length of your string and apply one of two formatters.

DateTimeFormatter fDateOnly = DateTimeFormatter.ofPattern( "MM/dd/uuuu" ) ;
DateTimeFormatter fDateTime = DateTimeFormatter.ISO_LOCAL_DATE_TIME ;

LocalDate ld = null ;
if( input.length() == 10 ) {
    try {
        ld = LocalDate.parse( input , fDateOnly ) ;
    } catch (DateTimeParseException  e ) {
    }
} else if ( input.length() == 19 ) {
    try {
        LocalDateTime ldt = LocalDateTime.parse( input , fDateTime ) ;
        ld = ldt.toLocalDate() ;
    } catch (DateTimeParseException  e ) {
    }
} else {
    // Received unexpected input.
}

String output = ld.format( fDateOnly ) ;

Remember that you can allow java.time to automatically localize when generating a string representing the value of your time, rather than hard code of a specific format. See DateTimeFormatter.ofLocalizedDate .

+1
source

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


All Articles