[Java] Inject a Clock via #now(Clock) to avoid implicit dependency on current time

The parameterless now() factory methods of the key classes in the java.time package implicitly use the system clock in the default time-zone.

In order to improve testability, there exists an overload now(Clock clock), which allows to inject a specified clock.
Using this method, tests of date/time related code become repeatable.

Refer to the documentation of java.time.Clock for more details.

Snippet of Noncompliant Code

final Instant instant = Instant.now(); // Noncompliant: implicitly depends on system clock
// [...] decisions or serialization based on the actual value of instant can't be tested reliably
final LocalDate today = LocalDate.now(); // Noncompliant
if (today.getDayOfWeek() == DayOfWeek.FRIDAY) {
   return "It's Friday!"; // code branch is only taken on Fridays, cannot be tested on other days
}

Snippet of Compliant Code

final Instant instant = Instant.now(clock); // Compliant: clock dependency can be injected and controlled
// [...] decisions or serialization based on actual value of instant can be tested reliably by injecting a specific clock
final LocalDate today = LocalDate.now(clock); // Compliant: injected clock dependency
if (today.getDayOfWeek() == DayOfWeek.FRIDAY) {
   return "It's Friday!"; // can be tested by injecting a clock that points to a Friday
}

External references and/or language specifications

Blog post explaining the issue and what should be done instead

Type

Code Smell

Tags

testability

There is a similar rule suggestion for .NET:

This rule should probably also flag usages of System.currentTimeMillis().

That rule have been implemented for .NET. :slight_smile: