[LEAPSECS] Java: ThreeTen/JSR-310
Keith Winstein
keithw at MIT.EDU
Fri Jan 28 17:09:20 EST 2011
Hi Stephen,
Aside from others' concerns, I am a little worried about the nonfunctional
nature of your API. The user might appreciate documentation about which
expressions may vary across calls to registerSystemLeapSecond(), and which
member functions are well-defined functions of the object and arguments
only. (And maybe some example test cases about the correct answer.)
For example, if you make Instant a = ofEpochSeconds( 1325375990 ) and
Instant b = ofEpochSeconds( 1325375991 ), and then take long d = between(
a, b ).toMillisLong(), what do you get?
It seems to me if I read your documentation correctly, that right now you
would get d = 1000. Then in a few months the IERS emails everybody to add
in a leap second, somebody calls registerSystemLeapSecond(), and suddenly
the *same code* will yield a different result -- d = 1001.
Do I understand correctly? If so, I think you are being a little glib to
tell the user that duration calculations with Instant "ignore leap
seconds." To the contrary: by using UTC-SLS, you are acknowledging the
existence of leap seconds, and you are making user-visible changes in
response to new information received about them, and your date-and-time
routines are no longer functions of the inputs -- they have side effects
based on ancillary calls to registerSystemLeapSecond(). I don't see how
you are ignoring them at all.
E.g., you say that "Instant uses the UTC-SLS time-scale which always has
86400 seconds in a day." But do you "always" have 86400000 milliseconds in
the day?
Another question I couldn't figure out from the documentation is whether
ofEpochMillis(x).toEpochMillisLong() is supposed to be an identity. It
seems like it might not be -- if a call to registerSystemLeapSecond()
happens in between, then this could yield a different output than what was
put in. Code could easily make this assumption so if it's rarely not true,
you should warn the user.
Another question is whether your notion of UTC-SLS EpochMillis will be
compatible with the operating system's POSIX epoch time_t (which often
just pauses on a leap second). I'm guessing it probably won't be, and
users may get in trouble here too without warning. E.g., the Python
time.time() function will give different results than your new definition
of "epoch" time.
Also it's not clear to me how you plan to distribute these historical leap
seconds. There is no historical leap second table in the GPS navigation
message that I am aware of, and no way to get one within the POSIX API
either. So it is a little tricky...
I raised these same issues when the Haskell people came on here five years
ago so I am not trying to pick on Java. :-) But I do think the issues are
probably subtle, and since UTC-SLS has never been implemented in any
widespread software, we do not really know what the issues are very well.
Being the very first implementation of UTC-SLS anywhere may put you on the
untested bleeding edge -- whether that's appropriate for this API is up to
you I guess.
Best,
Keith
On Fri, 28 Jan 2011, Stephen Colebourne wrote:
> I note that there has been some previous discussion about JSR-310 on
> this list. I thought I'd provide an update on the status wrt leap
> seconds (as spec lead) given Java is perhaps the most important
> enterprise programming language.
>
> The relevant classes for leap seconds are in this package:
> http://threeten.sourceforge.net/apidocs/javax/time/package-summary.html
>
> Instant is the class that will typically be used, and has 86400
> seconds in a day using the UTC-SLS definition. The Javadoc has the
> full explanation:
> http://threeten.sourceforge.net/apidocs/javax/time/Instant.html
>
> UTCInstant supports leap seconds based on a pluggable UTCRules class:
> http://threeten.sourceforge.net/apidocs/javax/time/UTCInstant.html
>
> TAIInstant represents the TAI scale:
> http://threeten.sourceforge.net/apidocs/javax/time/TAIInstant.html
>
> TimeSource allows an implementation to provide an accurate UTC/TAI
> clock if one is available:
> http://threeten.sourceforge.net/apidocs/javax/time/TimeSource.html
>
> Note that the UTC definition used states "The modern UTC time-scale
> was introduced in 1972, introducing the concept of whole leap-seconds.
> Between 1958 and 1972, the definition of UTC was complex, with minor
> sub-second leaps and alterations to the length of seconds. The default
> rules only implement UTC from 1972. Prior to that date, the default
> rules fix the UTC-TAI offset at 10 seconds. While not historically
> accurate, it is a simple, easy definition, suitable for this library.
> "
>
>
> Given the acrimony on this list, I'm sure there will be opinions on
> these design decisions (which differ from those last discussed here
> AFAICT). I'm looking for (constructive) feedback of all kinds,
> remembering that my goal is practical usage, not scientific purity.
> Also bear in mind that wide-adoption of this in Java may (or at least
> should) influence the future direction of standards.
>
> Interestingly, I started the process of looking into the topic with a
> strong dislike of leap-seconds, and a desire to remove them. I ended
> it with the strong desire to retain them exactly as at present, but
> with UTC-SLS for most users and separate UTC support for those that
> need it. This balanced the needs of most developers and business users
> to not care about leap seconds, with the reality that they exist.
>
> For reference, here is the explanation I previously sent to the
> ThreeTen mailing list:
>
> "
> There are four key elements of date/time that vary:
> - month lengths
> - leap years
> - DST
> - leap seconds
>
> The API handles each of these, but in different ways. Month lengths
> and leap years can be managed by DateResolver. DST by ZonedDateTime
> and ZoneResolver. Leap seconds by UTCInstant and UTCRules.
>
> However, the general prinicple of the API is that users care about
> these four elements in decreasing order. And specifically, almost
> no-one cares about leap seconds.
>
> The impact of the last statement is that the API only permits the
> second-of-minute to be from 0 to 59 inclusive. 60 is never a valid
> value. This is in accordance with most users expectations and makes a
> large API actually usable.
>
> (Without this simplification, every single user would need to take
> account of leap seconds. Trying to hide them in special methods like
> plusLeapSecond doesn't help. As a receiver of an object you don't know
> what state the class has been left in. In our initial approach, I
> indicated that simple Javadoc was a key goal. If the Javadoc is
> compex, then its a sign of multiple classes.)
>
> So, this lead to the question of how a date/time class, like
> OffsetDateTime, maps to the real time-line. With this change, the
> mapping is defined as UTC-SLS. This has the advantage that time always
> progresses forwards, given an accurate clock. Thus, OffsetDateTime is
> not 'just' a label, it also has a well-defined physical point for all
> moments prior to the next leap-second.
>
> Instant is an alternative view of OffsetDateTime. The two are always
> convertible exactly, however an Instant is always in the equivalent of
> +00:00 offset.
>
> UTCInstant exposes leap seconds accurately. UTCRules are applied in
> all instant conversions, and you need to convert a TAIInstnat to an
> Instant before converting to OffsetDateTime.
>
> As you say, TAIInstant is the only true "machine time".
>
> However...
>
> For most users that don't care about the subtleties of sub-second
> accuracy around leap seconds and just want to ignore them, they want
> something that they /believe/ is a "machine time". This is currently
> thought of as System.currentTimeMillis(). Instant is the replacement
> for that concept. Its "machine time" for most users that need a it,
> typically for an event time-stamp of some kind. InstantProvider is
> simply an interface to access this definition of Instant.
>
> TAIInstant (the correct "machine time") is theoretically a better
> choice, but is difficult to obtain, and not easily processed by ther
> systems, such as DB and XML. So, we have it for those specialist users
> that need it, but it is a low-importance class.
>
> So, the whole purpose of the design is to construct a successful
> mirage for our users so they don't ever have to deal with
> leap-seconds. UTC-SLS provides a clear definition for those that want
> to deal with higher accuracy time-sources. TAIInstant and UTCInstant
> deal with those that want to keep everything truly correct.
>
> On durations, the current code copes nicely with the differences
> between the UTC, TAI and 86400 definitions. A duration can be obtained
> as the difference between two points on any of the three scales. But
> it is not linked to any scale. They are effective seconds not SI
> seconds. Those that care about the difference should use TAIInstant
> throughout, and they will get SI seconds.
>
>
> In summary, if we were being truly honest in the API, then TAIInstant
> would be called Instant, and UTCInstant and Instant would disappear
> into the other human focussed classes. But our users don't want the
> truth - at least not around leap seconds - they want something in line
> with their conceptual model of time.
> "
>
> Feedback welcome.
>
> Stephen Colebourne
> Project lead ThreeTen
> Co-spec lead JSR-310
> https://sourceforge.net/apps/mediawiki/threeten/index.php?title=ThreeTen
> _______________________________________________
> LEAPSECS mailing list
> LEAPSECS at leapsecond.com
> http://six.pairlist.net/mailman/listinfo/leapsecs
>
More information about the LEAPSECS
mailing list