I am trying to validate and store date times with any offset into the database in UTC.
For validation, I am using
DateTimeFormatter.ISO_ZONED_DATE_TIME.parseUnresolved(dateString, new ParsePosition(0));
When called with an offset of -25:00, this throws java.time.DateTimeException: Value out of range: Hour[0-23], Minute[0-59], Second[0-59]
. For any other invalid strings, this returns null.
But when I am trying to parse it using
ZonedDateTime.parse(dateString)
when using a correct offset of -23:00, this throws Text '2012-04-23T18:25:43.511-23:00' could not be parsed: Zone offset not in valid range: -18:00 to 18:00
. If I look up the method definition, it seems like it is using the same parsing method DateTimeFormatter.ISO_ZONED_DATE_TIME
public static ZonedDateTime parse(CharSequence text) {
return parse(text, DateTimeFormatter.ISO_ZONED_DATE_TIME);
}
My question is, why are there different offset limits for parsing an ISO 8601 date times ?
CodePudding user response:
The documentation describes this difference here:
Parsing is implemented as a two-phase operation. First, the text is parsed using the layout defined by the formatter, producing a Map of field to value, a ZoneId and a Chronology. Second, the parsed data is resolved, by validating, combining and simplifying the various fields into more useful ones.
Five parsing methods are supplied by this class. Four of these perform both the parse and resolve phases. The fifth method,
parseUnresolved(CharSequence, ParsePosition)
, only performs the first phase, leaving the result unresolved. As such, it is essentially a low-level operation.
So the thing that parseUnresolved
does not do, but parse
does, is "validating [...] the various fields". In this case, parse
checks that the offset is within ChronoField.OFFSET_SECONDS.range()
(±18 hours). parseUnresolved
doesn't do this, just like how it doesn't check whether month 20 is a valid month:
System.out.println(
// this returns a non-null value
DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved(
"2021-20-20", new ParsePosition(0)
)
);
DateTimeException
is also a documented exception that parseUnresolved
can throw.
Throws:
DateTimeException
- if some problem occurs during parsing
It just so happens that parseUnresolved
doesn't recognise anything more than 24 hours as an offset when parsing an offset, during "the first phase".