Update AbsoluteDate.toString() for 11.0

Discussion on the forum: https://forum.orekit.org/t/update-absolutedate-tostring-for-11-0

Shortcomings

  • As #677 (closed) 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. others

Based on the discussion it seemed there was a preference for printing elapsed seconds since an epoch and date-time components in the TAI time scale.