9

I am trying to create a DateTimeformatter to validate following date times:

String date1 = "2017-07-06T17:25:28";
String date2 = "2017-07-06T17:25:28.1";
String date3 = "2017-07-06T17:25:28.12";
String date4 = "2017-07-06T17:25:28.123";
String date5 = "2017-07-06T17:25:28.1234";
String date6 = "2017-07-06T17:25:28.12345";
String date7 = "2017-07-06T17:25:28.123456";
String date8 = "2017-07-06T17:25:28.";

I have tried the following date time formatter to validate above dates:

public static final String DATE_TIME_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
                                   .appendPattern(DATE_TIME_FORMAT_PATTERN)
                                   .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
                                   .toFormatter();

It works fine for all the above dates, but according to my requirement it should fail with java.time.format.DateTimeParseException for date8.

Note: I am aware that I can achieve expected result with following formatter:

DateTimeFormatter formatter2 = DateTimeFormatter
                       .ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][.SSSSS][.SSSS][.SSS][.SS][.S]");

But I wanted to know that can we achieve expected result by changing in formatter1?

For parsing the date I am using following:

LocalDateTime.parse(date1, formatter1);
Amit Garg
  • 518
  • 1
  • 6
  • 17
  • 1
    What are DATE_TIME_FORMATTER and DATE_TIME_FORMAT_PATTERN ? – Pallavi Sonal Jul 06 '17 at 13:52
  • @PallaviSonal: thanks, I have updated my question. – Amit Garg Jul 06 '17 at 14:01
  • @AmitGarg Why did you unnaccept my answer? Is that any case that failed and I missed? –  Jul 06 '17 at 14:38
  • 1
    @Hugo; Thanks for your help. It is working fine, nothing wrong in your answer. As I have written this question just to learn about DateTimeFormatter, I am Just want to find more and more different answer on this question. I have noticed that I lot of time answer accepted questions are not seen by a lot of developer. This might be my personal experience. I will accept you answer tomorrow (Just waiting for some more different solutions) :) – Amit Garg Jul 06 '17 at 14:46
  • 1
    @AmitGarg Ok, got it! I thought that I had made some mistake... You're right, many people don't look at accepted questions. Thanks for clarifying it! –  Jul 06 '17 at 14:52

2 Answers2

13

You must create an optional section (using optionalStart() and optionalEnd() methods) containing the decimal point followed by 1 to 6 digits:

String DATE_TIME_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
    .appendPattern(DATE_TIME_FORMAT_PATTERN)
    // optional decimal point followed by 1 to 6 digits
    .optionalStart()
    .appendPattern(".")
    .appendFraction(ChronoField.MICRO_OF_SECOND, 1, 6, false)
    .optionalEnd()
    .toFormatter();

This parses from date1 to date7 and throws a java.time.format.DateTimeParseException with date8.


This also works the same way:

String DATE_TIME_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
    .appendPattern(DATE_TIME_FORMAT_PATTERN)
    // optional decimal point followed by 1 to 6 digits
    .optionalStart()
    .appendFraction(ChronoField.MICRO_OF_SECOND, 1, 6, true)
    .optionalEnd()
    .toFormatter();
  • 2
    `.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)` has always worked for me. Because if the minimum is `0`, it basically becomes optional... – Peter Dec 05 '18 at 20:11
  • Just what I needed, thank you. – ennth Feb 06 '21 at 18:45
-2

Try set minWidth to 1, i.e. .appendFraction(ChronoField.MICRO_OF_SECOND, 1, 6, true).

jingx
  • 2,853
  • 2
  • 19
  • 32