The default java.time.Clock implementation is based on System.currentTimeMillis(). As discussed for example here, Monotonically increasing time in Java?, it is not guaranteed to be monotonic.
And indeed, I regularly experience a situation, where the system time is automatically adjusted a few seconds to the past, and the java clock jumps back too.
//now() returns 2016-01-13T22:34:05.681Z
order.setCreationTime(Instant.now());
//... something happens, order gets cancelled
//now() returns 2016-01-13T22:34:03.123Z
//which is a few seconds before the former one,
//even though the call was performed later - in any reasonable sense.
//The recorded history of events is obviously inconsistent with the real world.
order.setCancelationTime(Instant.now());
It is then impossible to perform time-sensitive things, like recording and analysing event history, when one can not rely on time going only in one direction.
The aforementioned post says that System.nanoTime() is monotonic (if the underlying system supports it). So, if I want to base my code on the java.time API, I would need Clock that uses nanoTime internally to ensure one-way flow of the time. Maybe something like this would work. Or would't it?
public class MyClock() extends java.time.Clock {
private final long adjustment;
public MyClock() {
long cpuTimeMillis = System.nanoTime()/1000000;
long systemTimeMillis = System.currentTimeMillis();
adjustment = systemTimeMillis - cpuTimeMillis;
}
@Override
public long millis() {
long currentCpuTimeMillis = System.nanoTime()/1000000;
return currentCpuTimeMillis + adjustment;
}
}
It is just a sketch, not a full Clock implementation. And I suppose a proper implementation should also perform the adjustment against another Clock passed in the constructor, rather than directly against the currentTimeMillis().
Or, is there already such a monotonic Clock implementation available anywhere? I would guess there must have been many people facing the same issue.
Conclusion
Thanks for the inspiring comments and answers. There are several interesting points scattered across the comments, so I will summarize it here.
1. Monotonic clock
As for my original question, yes, it is possible to have monotonic clock that is not affected by system time jumping backwards. Such implementation can be based on System.nanoTime() as I suggested above. There used to be problems with this aproach in the past, but it should work fine on today's modern systems. This approach is already implemented for example in the Time4J library, their monotonic clock can be easily converted to java.time.Clock:
Clock clock = TemporalType.CLOCK.from(SystemClock.MONOTONIC);
2. Proper system time control
It it possible to configure system time management (ntpd in unix/linux), so that the system time virtually never moves back (it gets just slowed down if necessary), then one can rely on the system time being monotonic, and no clock-magic is necessary in Java.
I will go this way, as my app is server-side and I can get the time under control. Actually, I experienced the anomalies in an experimental environment that I installed myself (with only superficial knowledge of the domain), and it was using just ntpdate client (which can jump backwards if the time is out of sync), rather than ntpd (which can be configured so that it does not jump back).
3. Using sequences rather than clock
When one needs to track a strong relation what happened before what, it is safer to give the events serial numbers from an atomically generated sequence and not rely on the wall clock. It becomes the only option once the application is running on several nodes (which is not my case though).