1

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?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Nico
  • 49
  • 5
  • 4
    LocalDateTime uses the ISO-8601 model. Although RFC-3339 is largely identical, this is one of the disparities between them. Specifically, a negative zero offset is not allowed under ISO-8601. My guess is that Java is making a good faith effort to translate this and makes +00:00 instead (i.e. Z). You may need a custom class to handle this format. – vsfDawg Aug 08 '22 at 13:25
  • java.time handles a UTC offset as a count of seconds within +/- 18 hours so does not distinguish -0 from +0 (and renders 0 as `Z` as you have observed) and hence also does not support an unknown offset. Before parsing you may want an `if`-`else` construct with a condition like `timeStamp.matches(".*-[0:]+")` to filter out the timestamps that have an offset of minus 0, that is, unknown in RFC 3339. (I'm unsure about RFC 3339, but `OffsetDateTime.parse(CharSequence)` also accepts `-00:00:00` as an offset, and future releases may accept even more forms.) – Ole V.V. Aug 10 '22 at 03:43

1 Answers1

1

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • The strange offset `-00:00` is supposed to follow a time in UTC, according to the RFC. For all but the slightest intents and purposes, you ought to treat `-00:00` like it was `+00:00`. – eksortso Aug 19 '22 at 21:42
  • @eksortso No, you are very much incorrect. I added a quotation from the RFC saying just the opposite of your comment. A `-00:00` in RFC 3339 means ***unknown offset*** whereas `+00:00` means a ***known offset of zero***. You absolutely should *not* “treat -00:00 like it was +00:00”. They mean totally different things in RFC 3339, and in ISO 8601 one of the two does not exist. In terms of Java classes, this duality is be matched by `LocalDateTime` class which has no concept of offset or zone, and `Instant` class that represents a specific point on the timeline as seen from an offset of zero. – Basil Bourque Aug 20 '22 at 01:01
  • 1
    @BasilBourque Hmm? The quote says: "If the time in UTC is known". The absolute time (in UTC) is known, but it **cannot** be converted to a local time since the local timezone is unknown. Treating it as if it was a local time is therefore more or less the worst thing you could do, since its representation in local time is just the one thing you *don't* know (while do you know the absolute time, which on the other hand is unknown in `LocalDateTime`s). – Christian Siefkes Aug 21 '22 at 08:31