How to parse ZoneDateTime
from string that doesn\'t contain zone
and others fields?
Here is test in Spock to reproduce:
imp
The formatter has a withZone()
method that can be called to provide the missing time-zone.
ZonedDateTime.parse(
value,
DateTimeFormatter.ISO_ZONED_DATE_TIME.withZone(ZoneId.systemDefault()))
Bear in mind that there was a bug, so you need 8u20 or later for it to work fully.
Since the ISO_ZONED_DATE_TIME
formatter expects zone or offset information, parsing fails.
You'll have to make a DateTimeFormatter
that has optional parts for both the zone information and the time part.
It's not too hard reverse engineering the ZonedDateTimeFormatter
and adding optional tags.
Then you parse the String
using the parseBest()
method of the formatter. Then, for suboptimal parse results you can create the ZonedDateTime
using any default you want.
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.optionalStart() // time made optional
.appendLiteral('T')
.append(ISO_LOCAL_TIME)
.optionalStart() // zone and offset made optional
.appendOffsetId()
.optionalStart()
.appendLiteral('[')
.parseCaseSensitive()
.appendZoneRegionId()
.appendLiteral(']')
.optionalEnd()
.optionalEnd()
.optionalEnd()
.toFormatter();
TemporalAccessor temporalAccessor = formatter.parseBest(value, ZonedDateTime::from, LocalDateTime::from, LocalDate::from);
if (temporalAccessor instanceof ZonedDateTime) {
return ((ZonedDateTime) temporalAccessor);
}
if (temporalAccessor instanceof LocalDateTime) {
return ((LocalDateTime) temporalAccessor).atZone(ZoneId.systemDefault());
}
return ((LocalDate) temporalAccessor).atStartOfDay(ZoneId.systemDefault());