I am trying to write a DateTimeFormatter
that will allow me to take in multiple different String
formats, and then convert the String
formats to a specific type. Due to the scope of the project and the code that already exists, I cannot use a different type of formatter.
E.g., I want to accept MM/dd/yyyy
as well as yyyy-MM-dd'T'HH:mm:ss
but then when I print I only want to print to MM/dd/yyyy
format and have it in the format when I call LocalDate.format(formatter);
Could someone suggest ideas on how to do this with the 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.
The Answer by Andreas is correct and should be accepted.
Check length of string
As an alternative, you can simply test the length of your string and apply one of two formatters.
Be aware that you can let java.time automatically localize when generating a string representing the value of your date-time rather than hard-code a specific format. See DateTimeFormatter.ofLocalizedDate.
I've tested this with JDK 1.8.0_131 for Mac OS X and JDK 1.8.0111 for Windows (both worked).
I've created a
DateTimeFormatter
with optional sections (delimited by[]
), to parse both cases (MM/dd/yyyy
andyyyy-MM-dd'T'HH:mm:ss
).The same formatter worked for your case (
LocalDate
), but there are some considerations below.The output is:
PS: this works only with
LocalDate
. If I try to format an object with time fields (likeLocalDateTime
), both formats are used:This prints:
Note that it formatted with both patterns. My guess is that the formatter checks if the object has the fields in each optional section. As the
LocalDate
has no time fields (hour/minute/second), the second pattern fails and it prints only the first one (MM/dd/yyyy
). But theLocalDateTime
has all the time fields, and both patterns are valid, so both are used to format.My conclusion is: this isn't a general solution (like the Joda-Time's version), it's more like a "lucky" case where the patterns involved created the desired situation. But I wouldn't rely on that for all cases.
Anyway, if you are only using
LocalDate
, you can try to use this code. But if you're working with another types, then you'll probably have to use another formatter for the output, like this:The output is:
The parsing part can be written, and has been added in the ThreeTen-Extra library. The relevant code is here and is included below for clarity. The key trick is using
parseUnresolved()
to find out which format is correct:Unfortunately, there is no way to write a single
DateTimeFormatter
that supports flexible parsing and prints using a specific output format as per Joda-Time.What you're asking is not possible.
DateTimeFormatter
is afinal
class, so you cannot subclass it to implement your own behavior.The constructor is package-private, so you can't call it yourself. The only way to create a
DateTimeFormatter
is by using aDateTimeFormatterBuilder
. Note that thestatic
helper methods for creating aDateTimeFormatter
are internally usingDateTimeFormatterBuilder
, e.g.DateTimeFormatterBuilder
is also afinal
class, and cannot be subclassed, and it doesn't provide any methods for supplying multiple alternate formats to use, like you want.In short,
DateTimeFormatter
is closed and cannot be extended. If your code can only use aDateTimeFormatter
, then you are out of luck.