Search code examples
javadateparsingtimejava.time.instant

Java 8 date/time: instant, could not be parsed at index 19


I have following piece of code:

String dateInString = "2016-09-18T12:17:21:000Z";
Instant instant = Instant.parse(dateInString);

ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Europe/Kiev"));
System.out.println(zonedDateTime);

It gives me following exception:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2016-09-18T12:17:21:000Z' could not be parsed at index 19 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) at java.time.Instant.parse(Instant.java:395) at core.domain.converters.TestDateTime.main(TestDateTime.java:10)

When I change that last colon to a full stop:

String dateInString = "2016-09-18T12:17:21.000Z";

…then execution goes fine:

2016-09-18T15:17:21+03:00[Europe/Kiev]

So, the question is - how to parse date with Instant and DateTimeFormatter?


Solution

  • The "problem" is the colon before milliseconds, which is non-standard (standard is a decimal point).

    To make it work, you must build a custom DateTimeFormatter for your custom format:

    String dateInString = "2016-09-18T12:17:21:000Z";
    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_DATE_TIME)
        .appendLiteral(':')
        .appendFraction(ChronoField.MILLI_OF_SECOND, 3, 3, false)
        .appendLiteral('Z')
        .toFormatter();
    LocalDateTime instant = LocalDateTime.parse(dateInString, formatter);
    ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Europe/Kiev"));
    System.out.println(zonedDateTime);
    

    Output of this code:

    2016-09-18T12:17:21+03:00[Europe/Kiev]
    

    If your datetime literal had a dot instead of the last colon, things would be much simpler.