Search code examples
javadatedatetimeparsingrfc3339

How can I parse RFC 3339 date string into ZondeDateTime?


Problem:

I should parse an RFC3339 date string. It works fine with ISO_ZONED_DATE_TIME:

ZonedDateTime.parse("1985-04-12T23:20:50.52Z", ISO_ZONED_DATE_TIME);
ZonedDateTime.parse("1996-12-19T16:39:57-08:00", ISO_ZONED_DATE_TIME);

Let's say I'll fix a problem of Unknown Local Offset Convention just to not accept these dates. But I still have a problem with some corner cases like this:

  1990-12-31T23:59:60Z

This represents the leap second inserted at the end of 1990.

  1990-12-31T15:59:60-08:00

This represents the same leap second in Pacific Standard Time, 8
hours behind UTC."1990-12-31T15:59:60-08:00"

Question:

  • How can I parse it avoiding to lose any seconds?

Update:

  • Does it exist any alternative to ZonedDateTime that suits well RFC3339?

Solution

  • java.time doesn’t offer any direct support for what you want. Just earlier today I wrote this answer that also has a section on parsing a leap second. But what is said there is all there is.

    So there’s hand parsing left. I’d try something along these lines: Use a regular expression for detecting whether the second is 60. If so: Substitute it with 59. Parse. Convert to UTC. If the time of day in UTC is 23:59:59, assume there was a valid leap second in the original string; otherwise the string didn’t denote a valid time.

    I suggest that in case of a leap second second values up to 60.999999999 are valid. So to detect whether there is a 60 you need to look at what comes after the colon (if any) after the minutes, and not depend on whether there is a fractional part too.