1

When trying to convert from String to Local Date, an error is occurred and date cant be parsed

I am trying to convert a date which is in String format (eg: 2019-11-11T19:12:59.598) to Local Date (eg: 2019-11-11) format.

String dateInString = "2019-11-11T19:12:59.598";

public LocalDateTime DateToYear(String dateInString) {

    Instant instant = Instant.parse(dateInString);

    System.out.println("Instant : " + instant);

    //get date time only
    LocalDateTime result = LocalDateTime.ofInstant(instant, ZoneId.of(ZoneOffset.UTC.getId()));

    //get localdate
    System.out.println("LocalDate : " + result.toLocalDate());

    return result;


}

One of my test method is calling this method DateToYear(String dateInString).

aak
  • 75
  • 7
  • 1
    It will parse if you put a `Z` at the end of your string. See [`DateTimeFormatter.ISO_INSTANT`](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_INSTANT) – khelwood Nov 11 '19 at 19:22
  • 2
    Why are you using `Instant`? Wouldn't it make more sense to use the `parse` method in `LocalDateTime` directly? You could use `DateTimeFormatter.ISO_LOCAL_DATE_TIME` as your formatter. – Dawood ibn Kareem Nov 11 '19 at 19:31

2 Answers2

4

ISO 8601

Your input string complies with the ISO 8601 standard for textual date-time values.

The java.time classes use the standard formats by default when parsing/generating strings. So no need to specify a formatting pattern.

LocalDateTime

Your input string lacks an indicator of time zone or offset-from-UTC.

So we must parse as a LocalDateTime.

String dateInString = "2019-11-11T19:12:59.598";
LocalDateTime ldt = LocalDateTime.parse( input ) ;

Not a moment

Your input string does not represent a moment, is not a point on the timeline. Without the context of a time zone or offset, we do not know if you meant 7 PM on November 11 this year in Tokyo Japan, or 7 PM in Tunis Tunisia, or 7 PM in Toledo Ohio. These are all different moments, happening several hours earlier/later than one another. All we know is this string meant 7 PM on that date somewhere, but we know not where — so we know not when precisely.

To simply extract the date-only portion from your LocalDateTime, call toLocalDate.

LocalDate ld = ldt.toLocalDate() ;

Because your input is not a moment, your line:

Instant instant = Instant.parse(dateInString);

…makes no sense. An Instant represents a moment in UTC, a specific point on the timeline. But your string is not necessarily intended for UTC; we simply do not know what offset/zone was intended. We cannot tell that by looking at just the string.

If you happen to know for certain that input string was meant for UTC:

  • Educate the people who published that data about the importance of zone/offset. If they meant UTC, they should have appended a +00:00 or the abbreviation Z (pronounced “Zulu”).
  • Apply the constant ZoneOffset.UTC to get a OffsetDateTime which represents a moment as seen in a particular offset-from-UTC.

Code:

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;  // Making a moment of ambiguous input. Do this only if you are *certain* of the zone/offset intended by the publisher of this data input.

Get the date for that moment as seen in that offset.

LocalDate localDate = odt.toLocalDate() ;

If you know for certain the input string was meant for a particular time zone, apply a ZoneId to get a ZonedDateTime object. Then extract a LocalDate.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
LocalDate localDate = zdt.toLocalDate() ;

Keep in mind that for any given moment the date varies around the globe by time zone. So the LocalDate here may represent a different date than seen in the input string, being a day ahead or behind the date of the input string.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
2

It will parse if you put a Z at the end of your string. See DateTimeFormatter.ISO_INSTANT

jshell> Instant.parse("2019-11-11T19:12:59.598")
|  java.time.format.DateTimeParseException thrown: Text '2019-11-11T19:12:59.598' could not be parsed at index 23
|        at DateTimeFormatter.parseResolved0 (DateTimeFormatter.java:2046)
|        at DateTimeFormatter.parse (DateTimeFormatter.java:1948)
|        at Instant.parse (Instant.java:395)
|        at (#10:1)

jshell> Instant.parse("2019-11-11T19:12:59.598Z")
    ==> 2019-11-11T19:12:59.598Z
khelwood
  • 55,782
  • 14
  • 81
  • 108
  • To be clear as to why the "Z" is needed. It stands for "Zulu time", or GMT(Greenwich Mean Time). It's a timezone. – Jon Nov 11 '19 at 19:27