we are having a piece of code where we are using NanoClock to get the exact time. In a nut shell below is the code snippet of how i am generating the nano time and how we are converting to simple date format. the problem is, nono time (in some cases) is off by few seconds. so for eg, the system time is 12:23:44.125 the nano time will be 12:23:56.1234567.
public static Date getTimeStamp() {
final Clock clock = new NanoClock();
Instant instant = Instant.now(clock);
return Timestamp.from(instant);
}
public static Date getTimeInMilis(Timestamp timestamp) throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String miliDate = dateFormat.format(timestamp);
return dateFormat.parse(miliDate);
}
we are using NanoClock as follows
public static final long NANOS_PER_SECOND = 1000000000;
private static final long EPOCH_NANOS = System.currentTimeMillis() * 1000000;
private static final long NANO_START = System.nanoTime();
final long now = System.nanoTime() - NANO_START + EPOCH_NANOS;
return Instant.ofEpochSecond(now / NANOS_PER_SECOND, now % NANOS_PER_SECOND);
we were running this code in production for over 5 years and it was always fine. it started giving this discrepancy since past 2 months. we are using JAVA 8 update 71 (64 bits) and nothing has changed on the system with respect to JAVA or my code in past 4-5 months.
The discrepancy is due to system clock drift.
System.currentTimeMillis()is vulnerable to adjustments in the system clock, for example from the NTP daemon. On the other handSystem.nanoTime()is a value that increases by 109 every second, irrespective of any adjustments to the system clock.Whenever there is such an adjustment, you will get a divergence between
NanoClock, which callsSystem.currentTimeMillis()once and stores its result, and something which callsSystem.currentTimeMillis()each time, likenew Date().NanoClockis buggy.System.currentTimeMillis()returnsXwhile the current time isX milliseconds + Y microseconds + Z nanoseconds.So
EPOCH_NANOSisY microseconds + Z nanosecondsbefore the correct epoch.Note that
System.nanoTime()provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes).From Java 9 onwards,
Instant.now()gives you the current system time with nanosecond precision (but not nanosecond resolution).