1

The following works perfectly:

String startDate = "2019-10-12T00:00:00.000-07:00"

LocalDateTime startDateTime = LocalDateTime.parse(startDate,
    DateTimeFormatter.ISO_ZONED_DATE_TIME);

However, for the following code:

String startDate = "2019-10-12T00:00:00.000+07:00"

LocalDateTime startDateTime = LocalDateTime.parse(startDate,
    DateTimeFormatter.ISO_ZONED_DATE_TIME);

I get an exception:

throws java.time.format.DateTimeParseException: Text '2019-10-12T00:00:00.000 07:00' could not be parsed at index 23

Can someone help me understand what might be possibly wrong here?

4
  • 1
    Please take some time to familiarize with the editor and format your question properly, thanks. Commented Feb 14, 2019 at 20:24
  • 1
    Voting to close, can not reproduce. Create a minimal reproducible example. Also, the error message does not line up with the code you show. The message has no + or - at the zone, but a space. It is highly likely that the error message comes from a code version which you do not show here. I.e. a version with a space in the message, instead of a + or -. Which is obviously wrong, since this part is meant to tell the time offset, so either + or - in relation. Commented Feb 14, 2019 at 20:29
  • 3
    I bet that the 2019-10-12T00:00:00.000+07:00 date string is a URL query string parameter, and the + is decoded to space, because the + should have been encoded as %2B. Only reason I can think of for why a + was converted to a space. Commented Feb 14, 2019 at 20:47
  • @Andreas It seems that you may post that as an answer if you like. Commented Feb 14, 2019 at 21:58

3 Answers 3

6

tl;dr

(A) As mentioned in comment by Andreas, the disappearance of your + character in error message is suspicious. You likely have a character encoding problem. We here do not have enough info to diagnose that.

(B) Use OffsetDateTime rather than LocalDateTime, to fit your data.

OffsetDateTime
.parse( "2019-10-12T00:00:00.000+07:00" )
.toInstant()
.toString()

2019-10-11T17:00:00Z

See this code run live at IdeOne.com.

LocalDateTime is the wrong class

The LocalDateTime class lacks any concept of time zone or offset-from-UTC. So it cannot, by definition, represent a moment. A LocalDateTime object is not a point on the timeline.

Yet your input string indicates an offset-from-UTC, the +07:00 in 2019-10-12T00:00:00.000+07:00. Your attempt to put this value in a LocalDateTime is a misfit, a square peg in a round hole.

Never use LocalDateTime when you mean a specific moment, a specific point on the timeline. This class is almost never used in business-oriented apps for present or past moments. When making appointments in the future, this class should be used when you want the time-of-day to remain the same regardless of politicians redefining the region’s time zone.

OffsetDateTime

Parse as an OffsetDateTime object.

Your input string happens to comply fully with the ISO 8601 standard for textual date-time formats. The java.time classes use these formats by default when parsing/generating strings. So no need to specify a formatting pattern.

String input = "2019-10-12T00:00:00.000+07:00" ;
OffsetDateTime odt = OffsetDateTime.parse( input ) ;

UTC

To adjust to the wall-clock time of UTC (an offset of zero), call OffsetDateTime::withOffsetSameInstant. For your convenience, use the constant ZoneOffset.UTC.

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;

Or simply extract an object of the basic building-block class in java.time, an Instant. An Instant is always in UTC, by definition.

Instant instant = odt.toInstant() ;

ZonedDateTime

To see the same moment as viewed through the wall-clock time used by the people of a particular region (a time zone), apply a ZoneId to get a ZonedDateTime.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Sign up to request clarification or add additional context in comments.

Comments

4

I tried running both dates locally with the same parsing of the LocalDateTime, and they both run correctly.

I could recreate your same error by using a different date (note the space at the zone offset, instead of a + or -) 2019-10-12T00:00:00.000 07:00 instead of 2019-10-12T00:00:00.000+07:00. Which is what your error message shows (but not what your code has).

Are you sure that the code version you show, which uses 2019-10-12T00:00:00.000+07:00, is the actual version that produces the error? It looks like you have been using 2019-10-12T00:00:00.000 07:00, which then leads to the error.

2 Comments

I am sending the string as a request param and using postman to test it. Can that be a possible cause of error. I should have mentioned that earlier.
Of course, @AnkitaSingh, you are correct. You need to URL encode the string.
-2

there is an extra zero in the startDateTime use startDateTime = "2019-10-12T00:00:00.00+07:00"

6 Comments

Milliseconds are 3 digits (HH:mm:ss.SSS) because 1,000 milliseconds = 1 second
public static final DateTimeFormatter ISO_ZONED_DATE_TIME The ISO-like date-time formatter that formats or parses a date-time with offset and zone, such as '2011-12-03T10:15:30+01:00[Europe/Paris]'. see this documentation docs.oracle.com/javase/8/docs/api/java/time/format/… also dotnetcodr.com/2015/01/11/… it does not required 3 digits time
The example provided ("10:15:30") is in the format "HH:mm:ss" there are no milliseconds in that example.
I verified for request param = "2019-01-28T13:00:00.000+01:00" postman sends the date as "2019-01-28T13:00:00.000 01:00". That is the cause of error. If I run the API using Swagger it works fine.
DateTimeFormatter ISO_ZONED_DATE_TIME accepts anything from 0 through 9 decimals on the seconds. This is not the issue.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.