Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the (Oracle) Java JVM know a leap second is occurring?

A leap second will occur on June 30, 2015. Different Operating Systems seem to handle this situation differently. In my particular case, we are running a Red Hat 6.4 system with custom Java (JDK 1.7) software that is heavily time-dependent. According to some recent Red Hat released information I found, our system's NTP daemon will ensure the OS automatically handle the leap second by repeating 23:59:59 twice.

My question is: if I have a long running JDK 1.7 process, how does it know that a leap second is occurring? What I mean is, how does Java ultimately know the IERS people have decided to insert a leap second? The Date documentation seems to indicate is aware of leap seconds, but seems unhelpfully vague. Can I assume the JDK, when the appropriate Date object is constructed or Calendar.getInstance() is invoked, it is a pass through to the underlying OS's date-time handling to get the appropriate "real" time value? (Which, in my case, sounds like it would repeat second 23:59:59, because that's how the OS will handle it).

like image 206
Ogre Psalm33 Avatar asked Jun 22 '15 15:06

Ogre Psalm33


1 Answers

The Answer by assylias is correct. This Answer adds some thoughts triggered by a comment on that Answer. The comment referred to calculating elapsed time over the midnight when a Leap Second is scheduled.

This Answer does address the original Question as well by pointing out that for practical usage, the issue of Leap Second is moot, ignored by the date-time frameworks.

Leap Seconds Ignored

All the common Java date-time frameworks ignore leap seconds, as I understand it. These include:

  • java.time
  • Joda-Time
  • java.util.Date/.Calendar (now outmoded by java.time & Joda-Time)

Doc

Here are excerpts from each frameworks documentation showing they effectively ignore Leap Seconds. The emphasis in bold is mine.

The java.time doc for Instant class:

… Given the complexity of accurate timekeeping described above, this Java API defines its own time-scale, the Java Time-Scale.

The Java Time-Scale divides each calendar day into exactly 86400 subdivisions, known as seconds. These seconds may differ from the SI second. It closely matches the de facto international civil time scale, the definition of which changes from time to time.

The Java Time-Scale has slightly different definitions for different segments of the time-line, each based on the consensus international time scale that is used as the basis for civil time. Whenever the internationally-agreed time scale is modified or replaced, a new segment of the Java Time-Scale must be defined for it. Each segment must meet these requirements:

  • the Java Time-Scale shall closely match the underlying international civil time scale;
  • the Java Time-Scale shall exactly match the international civil time scale at noon each day;
  • the Java Time-Scale shall have a precisely-defined relationship to the international civil time scale.

There are currently, as of 2013, two segments in the Java time-scale.

For the segment from 1972-11-03 (exact boundary discussed below) until further notice, the consensus international time scale is UTC (with leap seconds). In this segment, the Java Time-Scale is identical to UTC-SLS. This is identical to UTC on days that do not have a leap second. On days that do have a leap second, the leap second is spread equally over the last 1000 seconds of the day, maintaining the appearance of exactly 86400 seconds per day.

For the segment prior to 1972-11-03, extending back arbitrarily far, the consensus international time scale is defined to be UT1, applied proleptically, which is equivalent to the (mean) solar time on the prime meridian (Greenwich). In this segment, the Java Time-Scale is identical to the consensus international time scale. The exact boundary between the two segments is the instant where UT1 = UTC between 1972-11-03T00:00 and 1972-11-04T12:00.

Implementations of the Java time-scale using the JSR-310 API are not required to provide any clock that is sub-second accurate, or that progresses monotonically or smoothly. Implementations are therefore not required to actually perform the UTC-SLS slew or to otherwise be aware of leap seconds. JSR-310 does, however, require that implementations must document the approach they use when defining a clock representing the current instant. See Clock for details on the available clocks.

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

Joda-Time FAQ:

Joda-Time does not support leap seconds. Leap seconds can be supported by writing a new, specialized chronology, or by making a few enhancements to the existing ZonedChronology class. In either case, future versions of Joda-Time will not enable leap seconds by default. Most applications have no need for it, and it might have additional performance costs.

The java.util.Date class doc:

A second is represented by an integer from 0 to 61; the values 60 and 61 occur only for leap seconds and even then only in Java implementations that actually track leap seconds correctly.

As far as I know, the OpenJDK and Oracle-provided implementations do not track leap seconds. Please post such documentation if you find it.

No Leap Second When Calculating Elapsed Time

Accordingly, these frameworks will not report the extra leap second when calculating elapsed time.

Here is some example code calculating elapsed time from minute before midnight to minute after, on June 30 to July 1, 2015 when a Leap Second is scheduled. This code tests Joda-Time 2.8.1 and java-time in java version "1.8.0_45". I ignored java.util.Date/.Calendar as I avoid those classes whenever possible; feel free to add code here for that case if desired.

First Joda-Time.

// Joda-Time 2.8.1 DateTime startJoda = new DateTime( 2015, 06, 30, 23, 59, 00, DateTimeZone.UTC ); DateTime stopJoda = new DateTime( 2015, 07, 01, 00, 01, 00, DateTimeZone.UTC ); long elapsedMillisJoda = ( stopJoda.getMillis( ) - startJoda.getMillis( ) );  System.out.println( "startJoda: " + startJoda + " stopJoda: " + stopJoda + " = elapsedMillisJoda: " + elapsedMillisJoda ); 

… and java.time …

// java.time ZonedDateTime startZdt = ZonedDateTime.of( 2015, 06, 30, 23, 59, 00, 00, ZoneOffset.UTC ); ZonedDateTime stopZdt = ZonedDateTime.of( 2015, 07, 01, 00, 01, 00, 00, ZoneOffset.UTC ); long elapsedMillisZdt = startZdt.until( stopZdt, ChronoUnit.MILLIS );  System.out.println( "startZdt: " + startZdt + " stopZdt: " + stopZdt + " = elapsedMillisZdt: " + elapsedMillisZdt ); 

When run, we see a result of even numbers, exactly two minutes, 120 seconds, or 120,000 milliseconds.

startJoda: 2015-06-30T23:59:00.000Z stopJoda: 2015-07-01T00:01:00.000Z = elapsedMillisJoda: 120000 startZdt: 2015-06-30T23:59Z stopZdt: 2015-07-01T00:01Z = elapsedMillisZdt: 120000 

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

like image 89
Basil Bourque Avatar answered Sep 20 '22 01:09

Basil Bourque