Java 8 Date equivalent to Joda's DateTimeFormatterBuilder with multiple parser formats?
There is no direct facility to do this, but you can use optional sections. Optional sections are enclosed inside squared brackets []
. This allows for the whole section of the String to parse to be missing.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(""
+ "[yyyy/MM/dd HH:mm:ss.SSSSSS]"
+ "[yyyy-MM-dd HH:mm:ss[.SSS]]"
+ "[ddMMMyyyy:HH:mm:ss.SSS[ Z]]"
);
This formatter defines 3 grand optional sections for the three main patterns you have. Each of them is inside its own optional section.
Working demo code:
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));
}
As an alternative answer to Tunaki, you can also use DateTimeFormatterBuilder:
DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
.appendPattern("[yyyy]")
.appendPattern("[M/d/yyyy]")
.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.toFormatter()
Iterating over @Tunaki's solution, using streams, when the code need to accept different patterns in a configurable way :
DateTimeFormatter dateTimeFormatter = dateFormats.stream()
.map(DateTimeFormatter::ofPattern)
.reduce(new DateTimeFormatterBuilder(),
DateTimeFormatterBuilder::appendOptional,
(f1, f2) -> f1.append(f2.toFormatter()))
.toFormatter();
In this case I don't care about the combiner part of the reducer, but I need it in the signature so I made the combiner correct.
This code would virtually equivalent to if the above patterns (yyyy/MM/dd HH:mm:ss.SSSSSS
, yyyy-MM-dd HH:mm:ss[.SSS]
, ddMMMyyyy:HH:mm:ss.SSS[ Z]
) would be fed to the stream :
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();