36

Is there a way how to create JSR-310 formatter that is able to parse both following date/times with variable length of seconds fraction?

2015-05-07 13:20:22.276052

or

2015-05-07 13:20:22.276

Example code:

DateTimeFormatter formatter
= new java.time.format.DateTimeFormatterBuilder()
        .append( java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") )
        .appendOptional( java.time.format.DateTimeFormatter.ofPattern(".SSSSSS") )
        .toFormatter();
formatter.parse("2015-05-07 13:20:22.276052", LocalDateTime::from);
JodaStephen
  • 57,570
  • 15
  • 91
  • 113
JiriS
  • 6,081
  • 4
  • 29
  • 40

3 Answers3

57

This solves the problem:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendPattern("yyyy-MM-dd HH:mm:ss")
    .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
    .toFormatter();

System.out.println(LocalDateTime.parse("2015-05-07 13:20:22.276052", formatter));
System.out.println(LocalDateTime.parse("2015-05-07 13:20:22.276", formatter));
System.out.println(LocalDateTime.parse("2015-05-07 13:20:22", formatter));

// output
2015-05-07T13:20:22.276052
2015-05-07T13:20:22.276
2015-05-07T13:20:22

The answer by JiriS is incorrect, as it uses appendValue whereas the correct way is to use DateTimeFormatterBuilder.appendFraction (which also handles the decimal point). The difference can be seen in the second system out, where appendValue incorrectly parses "2015-05-07T13:20:22.000276".

When parsing, LocalDateTime.parse(str, formatter) is a neater approach than using the formatter directly in most cases.

When using the builder, take advantage of appendPattern() and optionalStart() to keep things neat.

Community
  • 1
  • 1
JodaStephen
  • 57,570
  • 15
  • 91
  • 113
  • Here you recommend using `LocalDateTime.parse` rather than using the formatter directly. Yet the doc for [`DateTimeFormatter.parse`](http://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#parse-java.lang.CharSequence-java.time.temporal.TemporalQuery-) says just the opposite: “Most applications should use this method for parsing.” … `LocalDateTime dt = parser.parse(str, LocalDateTime::from);` – Basil Bourque Feb 05 '16 at 01:38
  • I see the confusion. The phrase "Most applications should use this method for parsing" is wrt the other parse methods in `DateTimeFormatter`. It wasn't intended as a comparison against the `parse()` methods on classes like `LocalDate`. Thus my answer is correct, users should prefer `LocalDate.parse` to `DateTimeFormatter.parse`. – JodaStephen Feb 08 '16 at 12:01
  • 2
    Is there a way to create such a formatter with **only** a pattern string? – a_horse_with_no_name Jun 01 '16 at 18:58
  • 2
    No. Patterns are a subset of the possible formatters. – JodaStephen Jun 03 '16 at 13:31
  • FYI to people seeing this years after it was written - that `appendFraction` signature does not appear to be in the latest couple of releases (at least on Maven Central, 2.9.9+). I couldn't find any alternative that worked for microseconds. – micseydel Jun 14 '18 at 21:37
1

And this one works

DateTimeFormatter formatter
= new java.time.format.DateTimeFormatterBuilder()
        .append( java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") )
        .appendOptional(
                new java.time.format.DateTimeFormatterBuilder()
                    .appendLiteral('.')
                    .appendValue( ChronoField.MICRO_OF_SECOND, 1, 6, SignStyle.NOT_NEGATIVE).toFormatter())
        .toFormatter();
JiriS
  • 6,081
  • 4
  • 29
  • 40
  • This Answer’s use of `appendValue` does not work in all cases. See the [Answer by JodaStephen](http://stackoverflow.com/a/30107522/642706) for details. – Basil Bourque Feb 05 '16 at 01:40
0

Parsing fails with a datetime without any ":" characters:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendPattern("yyyyMMddHHmmss")
            .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 9, false)
            .toFormatter();
        System.out.println(LocalDateTime.parse("20150507132022123", formatter));

Edit: it was appendFraction() which expects "." character.

procrastinator
  • 2,276
  • 17
  • 25
  • 33
mikmoila
  • 1
  • 1