Reputation: 676
I am trying to use Java 8 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. While
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 fine.
Cause of the exception is:
java.time.format.DateTimeParseException: Text '02/05/16 11:51.12.083 +04:30' could not be parsed at index 22
Am I doing something wrong?
Upvotes: 7
Views: 13864
Reputation: 328598
If you read the javadoc of DateTimeFormatter
, you will find a section detailing how to use the Z
offset (emphasis mine):
Offset Z: This formats the offset based on the number of pattern letters. One, two or three letters outputs the hour and minute, without a colon, such as '+0130'. The output will be '+0000' when the offset is zero. Four letters outputs the full form of localized offset, equivalent to four letters of Offset-O. The output will be the corresponding localized offset text if the offset is zero. Five letters outputs the hour, minute, with optional second if non-zero, with colon. It outputs 'Z' if the offset is zero. Six or more letters throws IllegalArgumentException.
So using 5 Z
s 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"));
Note that you can obtain similar results with:
z
zz
zzz
zzzz
xxx
XXX
xxxxx
XXXXX
Upvotes: 13
Reputation: 111142
Using DateTimeFormatterBuilder
to get exact control of the parser 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);
Upvotes: 1
Reputation: 6471
You need to use XXX
for the zone offset. 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 parse with LocalDateTime
as well, but the zone offset will be truncated.
Upvotes: 0
Reputation: 676
I found the answer in this post Unparsable Date with colon-separated timezone
In order to parse a timestamp that carries a timezone with a semicolon instead of X or Z as the DateFormatter javadoc indicates, you need to use XXX. All the following work:
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"))
Upvotes: 2