Optional parts in SimpleDateFormat
JSR-310 has been delivered with Java 8 which provides enhanced support for parsing temporal values where components may now be optional. Not only can you make the zone optional, but you can also make the time component optional and return the correct temporal unit for the given string.
Consider the following test cases.
public class DateFormatTest {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"yyyy-MM-dd[[ ]['T']HH:mm[:ss][XXX]]");
private TemporalAccessor parse(String v) {
return formatter.parseBest(v,
ZonedDateTime::from,
LocalDateTime::from,
LocalDate::from);
}
@Test public void testDateTime1() {
assertEquals(LocalDateTime.of(2014, 9, 23, 14, 20, 59),
parse("2014-09-23T14:20:59"));
}
@Test public void testDateTime2() {
assertEquals(LocalDateTime.of(2014, 9, 23, 14, 20),
parse("2014-09-23 14:20"));
}
@Test public void testDateOnly() {
assertEquals(LocalDate.of(2014, 9, 23), parse("2014-09-23"));
}
@Test public void testZonedDateTime() {
assertEquals(ZonedDateTime.of(2014, 9, 23, 14, 20, 59, 0,
ZoneOffset.ofHoursMinutes(10, 30)),
parse("2014-09-23T14:20:59+10:30"));
}
}
Here the DateTimeFormatter pattern of "yyyy-MM-dd[[ ]['T']HH:mm[:ss][XXX]]"
allows optionals within the square parentheses which can also be nested. Patterns can also be constructed from a DateTimeFormatterBuilder, which the above pattern is demonstrated here:
private final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.optionalStart()
.optionalStart()
.appendLiteral(' ')
.optionalEnd()
.optionalStart()
.appendLiteral('T')
.optionalEnd()
.appendOptional(DateTimeFormatter.ISO_TIME)
.toFormatter();
This would translate to an expression which looks like the following:
yyyy-MM-dd[[' ']['T']HH:mm[':'ss[.SSS]]].
Optional values can be nested and are also auto closed at the end if still open. Note however that there is no way to provide an exclusive OR on optional parts, thus the above format would actually parse the following value quite fine:
2018-03-08 T11:12
Note the really neat capability that we can reuse existing formatter's as parts of our current format.
I know this is an old post but just for the record...
Apache DateUtils class can help you with that.
String[] acceptedFormats = {"dd/MM/yyyy","dd/MM/yyyy HH:mm","dd/MM/yyyy HH:mm:ss"};
Date date1 = DateUtils.parseDate("12/07/2012", acceptedFormats);
Date date2 = DateUtils.parseDate("12/07/2012 23:59:59", acceptedFormats);
Link to the Apache Commons Lang library in Maven repository, you might want to check what's the latest version:
http://mvnrepository.com/artifact/org.apache.commons/commons-lang3
Maven v3.4
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
Gradle v3.4
'org.apache.commons:commons-lang3:3.4'