4

The clock accuracy on Windows seems to have changed lately. I remember it being very accurate since Windows 7 (1 ms resolution), and now the time hops in steps of 15 to 16 ms. I noticed due to some (albeit poorly written) unit tests failing (tests checked that some time elapsed between writing and reading records).

This affects following implementations:

  • System.currentTimeMillis()
  • LocalTime.now()
  • LocalDateTime.now()
  • ZonedDateTime.now()

I'm well aware that elapsed time is to be measured using System.nanoTime() deltas, but I'm wondering nevertheless if I missed something that changed back the clock resolution to 15-16ms.

Environment:

  • Windows 10 version 1709
  • JRE/JDK 1.8.0_171-b11 (64-bit)

Did anyone notice this as well? What could be the reason for this resolution change?

EDIT:
Test code to check this behaviour (see output: time changes and number of samples before change)

@Test public void testCurrentTimeMillis() { test(() -> System.currentTimeMillis()); } @Test public void testNanoTime() { test(() -> System.nanoTime()); } @Test public void testLocalTime() { test(() -> LocalTime.now()); } @Test public void testLocalDateTime() { test(() -> LocalDateTime.now()); } @Test public void testZonedDateTime() { test(() -> ZonedDateTime.now()); } private <T> void test(Supplier<T> timeSupplier) { int samples = 20; String lastTimeString = null; int count = 0; while (samples > 0) { count++; String timeString = timeSupplier.get().toString(); if (!timeString.equals(lastTimeString)) { System.out.println(timeString + " (" + count + ")"); lastTimeString = timeString; count = 0; samples--; } } } 
8
  • Do you have windows developer mode on? Commented Apr 25, 2018 at 13:14
  • @ShanuGupta: no, it's off (on 'Sideload Apps') Commented Apr 25, 2018 at 13:18
  • Can you turn on and check again? You might have to restart system. Commented Apr 25, 2018 at 13:19
  • Possible duplicate of Timer accuracy in java Commented Apr 25, 2018 at 13:31
  • @OleV.V. the other question dates back to 2009, back then such inacurracies were common on 32-bit Windows platforms. My case is a recent 64-bit Windows platform, where the problem resurfaced. Commented Apr 25, 2018 at 13:37

1 Answer 1

2

To get the local time with the best accuracy regardless of the platform, I came up with a solution with is based on the current time (measuring when it is increased) as an anchor, and and offset based on System.nanoTime() deltas.

Advantages:

  • current time with precision not depending on the platform
  • high accuracy (nano time)
  • portable (as the java.time objects can actually carry nanosecond precision).

Code (can be adapted to serve LocalTime and LocalDateTime as well):

/** * Exact zoned date/time, compensates for the 15-16ms leaps * of milliseconds time on some Java platforms. */ public final class ExactZonedDateTime { private static ZonedDateTime anchor; private static long anchorNanos; static { ZonedDateTime last = ZonedDateTime.now(); while (((anchor = ZonedDateTime.now()).equals(last))) { anchorNanos = System.nanoTime(); } } private ExactZonedDateTime() { } public static ZonedDateTime now() { return anchor.plusNanos(System.nanoTime() - anchorNanos); } } 

Subsequent calls:

2018-04-26T12:51:02.293079632+02:00[Europe/Zurich] 2018-04-26T12:51:02.293524865+02:00[Europe/Zurich] 2018-04-26T12:51:02.293598126+02:00[Europe/Zurich] 2018-04-26T12:51:02.293660770+02:00[Europe/Zurich] 2018-04-26T12:51:02.293725538+02:00[Europe/Zurich]

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.