Reputation: 1037
I am trying to build a DateTimeFormatter based on the https://stackoverflow.com/a/32964692/829542... to validate my input date. My logic requires the below formats to be valid
... with the micro seconds (SSSSSS) part in the above format being optional (or) if there were lesser number of digits provided for microseconds than the expected 6 digits precision - say 333 instead of 000333, i need to be able to pad, validate and process the date.
I am working through the DateTimeFormatter to build a custom formatter and arrived at the below -
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("yyyy")
.appendLiteral('-')
.appendValue(MONTH_OF_YEAR)
.appendLiteral('-')
.appendValue(DAY_OF_MONTH)
.appendLiteral('T')
.appendPattern(" HH:mm:ss")
.appendPattern("[.SSSSSS]")
.parseDefaulting(MICRO_OF_SECOND, MICRO_OF_SECOND.range().getMinimum())
.toFormatter();
But, this does not parse - for example "2016-08-04T20:43:30" as a valid date and also I am not sure how to pad the digits. I see that there is a pad methods available in the DateTimeFormatter, but I am not sure how to use them to get the desired result. Am I the only one feeling that there is a lot to consume with the Java Docs and follow!!
Any expert advise is appreciated!
Update 1:
Based on the answer from @mtj, was able to extend the solution to cover most of the problem. The only pending item now is to make the no. of micro seconds specified in the date flexible width from 0-6. Right now, only 0 and 6 digit width is valid.
public class Test {
public static void main(String[] args)
{
System.out.println("Date 1 - 2016-08-04T20:43:30 = " + Test.isValid("2016-08-04T20:43:30")); // true
System.out.println("Date 2 - 2016-08-04 20:43:30 = " + Test.isValid("2016-08-04 23:43:30")); // true
System.out.println("Date 3 - 2016-08-04T20:43:30.123121 = " + Test.isValid("2016-08-04T20:43:30.123121")); // true
System.out.println("Date 4 - 2016-08-04 20:43:30.123131 = " + Test.isValid("2016-08-04 20:43:30.123131")); // true
System.out.println("Date 5 - 2016-08-04'T'20:43:30.123121 = " + Test.isValid("2016-08-04'T'20:43:30.123121")); // true
System.out.println("Date 6 - 2016-08-04'T' 20:43:30.123121 = " + Test.isValid("2016-08-04'T' 20:43:30.123121")); // false (as expected)
System.out.println("Date 7 - 2016-08-04T20:43:30.123 = " + Test.isValid("2016-08-04T20:43:30.123")); // false
System.out.println("Date 8 - 2016-08-04T20:43:30.123 = " + Test.isValid("2016-08-04 20:43:30.123")); // false
}
public static boolean isValid(String inputDate)
{
DateTimeFormatter charLiteralTFormat = getDateFormat()
.appendOptional(new DateTimeFormatterBuilder().appendLiteral("'").toFormatter())
.appendOptional(new DateTimeFormatterBuilder().appendLiteral('T').toFormatter())
.appendOptional(new DateTimeFormatterBuilder().appendLiteral("'").toFormatter())
.append(getTimeFormat().toFormatter())
.toFormatter();
DateTimeFormatter spaceBtwnDttmFormat = getDateFormat()
.appendOptional(new DateTimeFormatterBuilder().appendLiteral(' ').toFormatter())
.append(getTimeFormat().toFormatter())
.toFormatter();
DateTimeFormatter[] formatters = {
charLiteralTFormat, spaceBtwnDttmFormat};
for(DateTimeFormatter formatter : formatters) {
try {
LocalDate.parse(inputDate, formatter);
return true;
} catch (DateTimeParseException e) {
//System.out.println(" Invalid Date ... ");
}
}
return false;
}
public static DateTimeFormatterBuilder getDateFormat(){
DateTimeFormatterBuilder baseFormat = new DateTimeFormatterBuilder()
.appendPattern("yyyy")
.appendLiteral('-')
.appendValue(MONTH_OF_YEAR)
.appendLiteral('-')
.appendValue(DAY_OF_MONTH);
return baseFormat;
}
public static DateTimeFormatterBuilder getTimeFormat() {
DateTimeFormatterBuilder timeFormat = new DateTimeFormatterBuilder()
.appendPattern("HH:mm:ss")
.appendOptional(new DateTimeFormatterBuilder().appendLiteral('.').toFormatter())
.appendOptional(new DateTimeFormatterBuilder().appendValue(ChronoField.MICRO_OF_SECOND,6).toFormatter());
return timeFormat;
}
}
Output
// Output -
// Validation going as expected
Date 1 - 2016-08-04T20:43:30 = true
Date 2 - 2016-08-04 20:43:30 = true
Date 3 - 2016-08-04T20:43:30.123121 = true
Date 4 - 2016-08-04 20:43:30.123131 = true
Date 5 - 2016-08-04'T'20:43:30.123121 = true
Date 6 - 2016-08-04'T' 20:43:30.123121 = false
// Output -
// Validation NOT going as expected
Date 7 - 2016-08-04T20:43:30.123 = false
Date 8 - 2016-08-04T20:43:30.123 = false
Upvotes: 2
Views: 480
Reputation: 3554
The problem with the example and input you posted is the blank preceeding the hour. Delete this, and it works.
Note however, that this will not parse both patterns you need.
I guess, the following will be closer to your requirements, even though it will accept the combination of 'T' and blank which should be illegal:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("yyyy")
.appendLiteral('-')
.appendValue(ChronoField.MONTH_OF_YEAR)
.appendLiteral('-')
.appendValue(ChronoField.DAY_OF_MONTH)
.appendOptional(new DateTimeFormatterBuilder().appendLiteral('T').toFormatter())
.appendOptional(new DateTimeFormatterBuilder().appendLiteral(' ').toFormatter())
.appendPattern("HH:mm:ss")
.appendOptional(new DateTimeFormatterBuilder().appendPattern(".SSSSSS").toFormatter())
.toFormatter();
Upvotes: 0