How to keep unknown local offset when converting from RFC3339?

496 Views Asked by At

I recieve a timestamp that follows the RFC3339 standard. The sender used the "Unknown Local Offset Convention" provided by RFC3339 as the users time preference is unkown, so I recieve a timestamp like 1970-01-01T00:00:00.0000-00:00 and I need to preserve the -00:00 information. I am currenlty parsing the recieved timestamp with

LocalDateTime localTimeStamp = LocalDateTime.parse(timeStamp, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
OffsetDateTime.of(localTimeStamp, ZoneOffset.of("-00:00"))

but this replaces the -00:00 with Z. Is there a way to keep the unkown local offset convetion, ideally with OffsetDateTime?

1

There are 1 best solutions below

3
Basil Bourque On

tl;dr

LocalDateTime
.parse( 
    "1970-01-01T00:00:00.0000-00:00"
    .replace( "-00:00" , "" )
)

Avoid RFC 3339

RFC 3339 is a self-proclaimed “profile” of the ISO 8601 standard. Unfortunately, RFC 3339 defines some unwise violations of that standard.

One of these violations is allowing an offset from UTC of negative zero hours-minutes-seconds. In contrast, ISO 8601 wisely forbids such a negative zero.

In the RFC the meaning of a negative zero offset is that the true offset is unknown. To quote the RFC:

4.3. Unknown Local Offset Convention

If the time in UTC is known, but the offset to local time is unknown, this can be represented with an offset of "-00:00". This differs semantically from an offset of "Z" or "+00:00", which imply that UTC is the preferred reference point for the specified time. RFC2822 [IMAIL-UPDATE] describes a similar convention for email.

In contrast, in ISO 8601 an unknown offset is simply omitted. Omission seems a much smarter course.

I suggest you educate the publisher of your data about the poor decisions employed in RFC 3339, and recommend they stick to ISO 8601 definitions.

LocalDateTime class

If you must parse strings with the negative zero offset, I suggest you perform simple string manipulation to strip it. Replace the -00:00 with empty string. Then parse as a LocalDateTime which purposely lacks the context of a time zone or offset. A LocalDateTime is simply a date with a time-of-day, nothing more.

String input = "1970-01-01T00:00:00.0000-00:00" ;
String modified = input.replace( "-00:00" , "" ) ;
LocalDateTime ldt = LocalDateTime.parse( modified ) ;

You asked:

Is there a way to keep the unkown local offset convetion, ideally with OffsetDateTime?

Using OffsetDateTime here makes no sense. That class represents a date and time as seen with with a particular offset. But you don’t know the intended offset. So you have only two of the three pieces required by OffsetDateTime.

Instead, LocalDateTime fits your need to represent a date and time without the context of an offset or time zone.