How to parse ZoneDateTime
from string that doesn't contain zone
and others fields?
Here is test in Spock to reproduce:
import spock.lang.Specification
import spock.lang.Unroll
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
@Unroll
class ZonedDateTimeParsingSpec extends Specification {
def "DateTimeFormatter.ISO_ZONED_DATE_TIME parsing incomplete date: #value #expected"() {
expect:
ZonedDateTime.parse(value, DateTimeFormatter.ISO_ZONED_DATE_TIME) == expected
where:
value | expected
'2014-04-23T04:30:45.123Z' | ZonedDateTime.of(2014, 4, 23, 4, 30, 45, 123_000_000, ZoneOffset.UTC)
'2014-04-23T04:30:45.123+01:00' | ZonedDateTime.of(2014, 4, 23, 4, 30, 45, 123_000_000, ZoneOffset.ofHours(1))
'2014-04-23T04:30:45.123' | ZonedDateTime.of(2014, 4, 23, 4, 30, 45, 123_000_000, ZoneId.systemDefault())
'2014-04-23T04:30' | ZonedDateTime.of(2014, 4, 23, 4, 30, 0, 0, ZoneId.systemDefault())
'2014-04-23' | ZonedDateTime.of(2014, 4, 23, 0, 0, 0, 0, ZoneId.systemDefault())
}
}
First two test passed, all others failed with DateTimeParseException:
- '2014-04-23T04:30:45.123' could not be parsed at index 23
- '2014-04-23T04:30' could not be parsed at index 16
- '2014-04-23' could not be parsed at index 10
How can I parse incomplete dates with time and zone setted to default?
Since the
ISO_ZONED_DATE_TIME
formatter expects zone or offset information, parsing fails. You'll have to make aDateTimeFormatter
that has optional parts for both the zone information and the time part. It's not too hard reverse engineering theZonedDateTimeFormatter
and adding optional tags.Then you parse the
String
using theparseBest()
method of the formatter. Then, for suboptimal parse results you can create theZonedDateTime
using any default you want.The formatter has a
withZone()
method that can be called to provide the missing time-zone.Bear in mind that there was a bug, so you need 8u20 or later for it to work fully.