Java 8 LocalDateTime ZonedDateTime cannot parse date with timezone

I am trying to use Java 8's new date pattern instead of Joda, and I have the following problem:

Both

ZonedDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS Z")) 

and

 LocalDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS Z")) 

throw 'java.time.format.DateTimeParseException' exception. Until

 org.joda.time.DateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormat.forPattern("dd/MM/yy HH:mm.ss.SSS Z")) 

works great.

Reason for exclusion:

java.time.format.DateTimeParseException: text '02 / 05/16 11: 51.12.083 +04: 30 'could not be parsed by index 22

Am I doing something wrong?

+5
source share
4 answers

If you read the javadoc DateTimeFormatter , you will find a section that describes in detail the use of the Z offset (selection)

Offset Z: formats the offset based on the number of letters of the patterns. One, two or three letters gives an hour and a minute without a colon, for example, "+0130". The output will be "+0000" when the offset is zero. Four letters display the full localized offset form equivalent to the four letters Offset-O. The result will be the corresponding localized offset text if the offset is zero. Five letters gives an hour, a minute, with an optional second, if not zero, with a colon . It produces "Z" if the offset is zero. Six or more letters throw an IllegalArgumentException.

Thus, using 5 Z will work as expected:

 ZonedDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS ZZZZZ")); 

Please note that you can get similar results with:

  • Z
  • zz
  • zzz
  • zzzz
  • xxx
  • xxx
  • xxxxx
  • xxxxx
+5
source

I found the answer in this post An opaque date with a colon separated time zone

To parse a timestamp that contains a time zone with a semicolon instead of X or Z, as specified in the DateFormatter javadoc parameter, you need to use XXX. All the following works:

 LocalDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS XXX")) OffsetDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS XXX")) ZonedDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS XXX")) 
+1
source

To offset the zone you need to use XXX . This will work for ZonedDateTime and OffsetDateTime

 ZonedDateTime.parse("02/05/16 11:51.12.083 +04:30", DateTimeFormatter.ofPattern("dd/MM/yy HH:mm.ss.SSS XXX")) 

It will also analyze using LocalDateTime , but the zone offset will be truncated.

0
source

Using DateTimeFormatterBuilder to get precise parser control and using appendOffsetId works:

 DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendValue(ChronoField.DAY_OF_MONTH, 2) .appendLiteral('/') .appendValue(ChronoField.MONTH_OF_YEAR, 2) .appendLiteral('/') .appendValueReduced(ChronoField.YEAR, 2, 2, 2000) .appendLiteral(' ') .appendValue(ChronoField.HOUR_OF_DAY) .appendLiteral(':') .appendValue(ChronoField.MINUTE_OF_HOUR) .appendLiteral('.') .appendValue(ChronoField.SECOND_OF_MINUTE) .appendLiteral('.') .appendValue(ChronoField.MILLI_OF_SECOND) .appendLiteral(' ') .appendOffsetId() .toFormatter(); OffsetDateTime.parse("02/05/16 11:51.12.083 +04:30", formatter); 
0
source

All Articles