Java NTP client

I need my software to communicate with an NTP server to determine the local clock offset. I have tried using the org.apache.commons.net.ntp package, but its implementation is rather poor when running on Windows, because of the use of System.currentTimeMillis() to determine the time before and after the NTP packet exchange. As you may or may not know, this value is only updated when the system clock ticks, which on most modern Win2k3 servers is at 64Hz or every 15.625ms. This greatly limits the accuracy of the clock offset calculation.

Ntpd uses the CPU high-frequency timer to interpolate between system clock ticks, and achieve much higher resolution time. Do you know of a Java implementation that uses this or a similar technique? Or do you know of any other NTP implementation other than Apache's?


there is a NTP Java implementation on support.ntp.org


Since this question ranks very high on Google for "Java NTP client":

Android has a nice, compact Apache-licensed implementation of a Simple NTP client: android.net.SntpClient.

It would need to be modified to run on non-Android java, but this should be trivial, since the code is about 100 lines of code plus another 100 lines of detailed comments, with no external dependencies except the Android system clock - and by chance, it is ready to accept relative timers like nanoTime() since it already uses such a relative timer.


I have written a java implementation (Java 7) that you can use: SntpClient


If you're using Java 5 or above, can you use System.nanoTime() to perform a more accurate measurement of time offsets ? You'd have to modify your existing NTP code, but you should have the source for it, and I wouldn't expect this to be difficult.


I know this is an old question but I notice that all the answers does not explain how to use those libraries. In this answer we will show a basic implementation and its logic behind.

A simple way to implement it is using Apache Commons Net library. This library will provide a NTPUDPClient class to manage connectionless NTP requests and return a TimeInfo instance. This instance should compute the offset between your system's time and the NTP server's time. Lets try to implement it here:

  1. Add the Apache Commons Net library to your project.
<dependency>
  <groupId>commons-net</groupId>
  <artifactId>commons-net</artifactId>
  <version>3.6</version>
</dependency>
  1. Create a new instance of the NTPUDPClient class.
  2. Setup the default timeout and the InetAddress of the NTP Server.
  3. Call the NTPUDPClient.getTime() method to retrieve a TimeInfo instance with the time information from the specified server.
  4. Call computeDetails() method to compute and validate details of the NTP message packet.
  5. Finally, get the offset and calculate an atomic time.

Here we have a basic implementation:

import java.net.InetAddress;
import java.util.Date;
import org.apache.commons.net.ntp.NTPUDPClient; 
import org.apache.commons.net.ntp.TimeInfo;

public class NTPClient {
  private static final String SERVER_NAME = "pool.ntp.org";

  private volatile TimeInfo timeInfo;
  private volatile Long offset;

  public static void main() throws Exception {

    NTPUDPClient client = new NTPUDPClient();
    // We want to timeout if a response takes longer than 10 seconds
    client.setDefaultTimeout(10_000);

    InetAddress inetAddress = InetAddress.getByName(SERVER_NAME);
    TimeInfo timeInfo = client.getTime(inetAddress);
    timeInfo.computeDetails();
    if (timeInfo.getOffset() != null) {
        this.timeInfo = timeInfo;
        this.offset = timeInfo.getOffset();
    }

    // This system NTP time
    TimeStamp systemNtpTime = TimeStamp.getCurrentTime();
    System.out.println("System time:\t" + systemNtpTime + "  " + systemNtpTime.toDateString());

    // Calculate the remote server NTP time
    long currentTime = System.currentTimeMillis();
    TimeStamp atomicNtpTime = TimeStamp.getNtpTime(currentTime + offset).getTime()

    System.out.println("Atomic time:\t" + atomicNtpTime + "  " + atomicNtpTime.toDateString());
  }

  public boolean isComputed()
  {
    return timeInfo != null && offset != null;
  }
}

You will get something like that:

System time:    dfaa2c15.2083126e  Thu, Nov 29 2018 18:12:53.127
Atomic time:    dfaa2c15.210624dd  Thu, Nov 29 2018 18:12:53.129