xirt
xirt

Reputation: 554

Dealing with Leap Seconds Correctly

Before and during a leap second, it appears that calling new Date() will return 23:59:59 twice (once before the leap second, and once during the leap second), rather than 23:59:59, and 23:59:60.

Is there a way (short of implementing an NTP client within the application, or checking for the clock to go backwards or repeat itself) to determine whether or not a given second is a leap second or not, so as to correctly present 23:59:60 to the user?

For that matter, do host operating systems have any hooks to determine whether or not it is pre or post leap second?

Upvotes: 3

Views: 1239

Answers (2)

Meno Hochschild
Meno Hochschild

Reputation: 44071

Let's look into the source code of java.util.Date:

public Date() {
    this(System.currentTimeMillis());
}

So the question can be read as:

Will System.currentTimeMillis() yield the leap second value 60 or even 61 (as the spec pretends)?

The answer is in strict sense: It depends on the underlying operating system. But fact is: All well known operating systems like Windows, Linux, Apple, Android are ignorant towards leap seconds. Instead These operating systems make any clock manipulations at any time (setting back etc., synchronizing with NTP-server...). So you will not observe a leap second using the Date-API. By the way, the value 61 is impossible because UTC-standard mandates that UTC will never deviate from UT1 by more than 0.9 secs with the consequence that a double leap second will not be inserted.

The origin of "61" is just a gross misunderstanding from early POSIX-specifications (where this mistake has been corrected now). Unfortunately the old Java-spec has not yet been corrected causing misunderstandings until now.

About Java-8:

Yes, the so-called "Java Time-Scale" is formally specified as UTC-SLS - based on an expired proposal whose intent was rather directed towards internal implementations of NTP-servers. No implementation of UTC-SLS exist in real world. Even Java-8 does not implement UTC-SLS. Two facts prove this statement:

  • Java-8 does not contain a leap second table (which would be the foundation of any UTC-SLS-implementation). The Threeten-project had originally hold such one but it was removed (now also removed from the backport).

  • The conversion from java.util.Date to Instant is just 1:1 (see source code - leaving aside the different precision millis vs. nanos). Note that java.util.Date is not mentioned in the API of Instant with respect to the so-called "Java Time scale".

The Java time-scale is used for all date-time classes. This includes Instant, LocalDate, LocalTime, OffsetDateTime, ZonedDateTime and Duration.

Furthermore: The origin of java.util.Date is from 1995 (when Java was invented) but UTC-SLS was proposed several years later.

So what is left in Java-8 as leap second support? Empty words in spec causing a lot of confusion, nothing else.

What can you do else? Within the scope of JDK simply nothing. What you need is an external 3rd-party library with built-in leap second data. An example is my library Time4J - see this article. Another option might be the library Threeten-Extra with its class UTCInstant. But I have not tested its conversion to java.util.Date (seems to be suspect?).

Upvotes: 8

brendan
brendan

Reputation: 308

According to the Java8 documentation for the Date class, calling Date during the leap second will/did correctly return :60 or :61.

So you don't need to do anything.

How it does that is a bit of mystery though, since the underlying Instant class spreads the leap second out over the last 1000 seconds of the day - so each of those last seconds will actually be 1.001 seconds long - and your application wont know whether it's in the leap second or not.

Upvotes: 2

Related Questions