Home > front end >  Difference between multiple ISO 8601 to ZonedDateTime parsing methods
Difference between multiple ISO 8601 to ZonedDateTime parsing methods

Time:09-17

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".

  • Related