Update AbsoluteDate.toString() for 11.0

Hi All,

For the next major release I would like to propose updating the implementation of AbsoluteDate.toString(). This method in particular is important because it is called in several places we cannot change. Such as in exception handling, test case failure messages, and the debugger. I will outline what I see as the shortcomings of the current implementation and a few possible new implementations. I would like to hear your thoughts on the issue.

Shortcomings

  • As #677 noted it does not return valid ISO 8601 event though it is documented to.
  • Limiting to millisecond precision creates strange error messages. E.g. “2020-01-01T00:00:00.000 is before 2020-01-01T00:00:00.000” when the two dates differ by less than 1ms.
  • In Effective Java Josh Bloch writes that the toString() method should be primarily for developers. He recommends making it an unambiguous representation of the object’s state. Since Orekit is a library written for other developers and given how toString() is used I agree. There are other methods for presenting dates to users.
  • It is in UTC which needs leap seconds to be loaded. Instances of AbsoluteDate can be created without loading leap seconds, but the toString() method doesn’t work, creating one of the most common errors in Orekit for new comers and experienced developers alike.
  • It uses the default data context. This can produce some strange error messages when an application is using a different data context as the leap second tables may be different. Also, this use of the default data context can only be detected at runtime using an ExceptionalDataContext, which is problematic.

Implementation Options

  1. Just keep the current implementation. The shortcomings are minor.
  2. Use TAI and extend the precision of the seconds field, and include "TAI" to denote the time scale. TAI is the de facto time scale of AbsoluteDate so no time scale conversions would need to be done. 16 digits after the decimal place would eliminate most ambiguity issues, but some ambiguity still exists for small values of AbsoluteDate.offset. TAI conversion is less complex and buggy than UTC conversion, as seen in the bugs reported concerning time. A reliable toString() is helpful for developers, especially in exception messages. The result would be neither ISO 8601 nor RFC 3339 since they require UTC or an integer number of minutes offset thereof. To generate those formats use toString(TimeScale) and related methods.
  3. Print the epoch and offset as stored internally in AbsoluteDate. Unambiguous but perhaps not that user friendly.
  4. Add epoch and offset using BigDecimal or similar class and convert the result to a string. The result would be seconds past the AbsoluteDate epoch. Should theoretically be unambiguous because of how those values are set. Needs some more investigation to see if it is possible to have epoch + offset sum to the same number but be set to different values. Perhaps this kind of ambiguity is not significant because equals, compareTo, and durationFrom are all computed based on the sum of epoch + offset.
  5. Combine 3 and 1 so the developer gets a description in calendar format and full precision, unambiguous representation of the AbsoluteDate. Something like "123456.789456123456789 (2020-01-01T00:00:00... TAI)".
  6. Combine 2 and 1.
  7. others?

Up until now the time scale and epoch of AbsoluteDate have been left as an implementation detail and not specified in documentation. The encapsulation is useful, but not complete - some numerical precision behavior of AbsoluteDate currently depends on those choices. Options 2 and 3 would make those choices part of the public API.

My preference would be for option 4. What do you think?

Regards,
Evan

Hi Evan,

What a great analysis!

I hesitate between 4 and 5. Is the only difference between 4 and 5 the fact that we print the mathematical addition of epoch and offset instead of printed both separately ?

However, I prefer option 4 too.

Bryan

Hi Evan,

Thank you for your proposal.
Option 4 is my preferred one too.

Regards,
Maxime

Yes, that’s correct.

I am good with #4 as well. Since this is 11 and breaking changes are allowed it’s a good release to do this in. However we probably need to put in big bold letters that this is happening and how to get the original behavior. I know a lot of code where they use the standard toString() method and expect a very specific string format to come out the other side (for better or worse).