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.
- 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
AbsoluteDatecan 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.
- Just keep the current implementation. The shortcomings are minor.
- 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
AbsoluteDateso 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.
- Print the
offsetas stored internally in
AbsoluteDate. Unambiguous but perhaps not that user friendly.
BigDecimalor similar class and convert the result to a string. The result would be seconds past the
AbsoluteDateepoch. Should theoretically be unambiguous because of how those values are set. Needs some more investigation to see if it is possible to have
epoch + offsetsum to the same number but be set to different values. Perhaps this kind of ambiguity is not significant because
durationFromare all computed based on the sum of
epoch + offset.
- 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)".
- Combine 2 and 1.
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?