Proposal for new interface: TimeSource

Stephen Colebourne scolebourne at joda.org
Thu May 6 23:27:41 UTC 2021


This is a proposal to add a new interface to java.time.*

  public interface TimeSource {
    public static TimeSource system() { ... }
    public abstract Instant instant();
    public default long millis() {
      return instant().toEpochMilli();
    }
    public default Clock withZone(ZoneId zoneId) {
      return Clock.of(this, zoneId);
   }
  }

The existing `Clock` abstract class would be altered to implement the interface.
A new static method `Clock.of(TimeSource, ZoneId)` would be added.
No changes are needed to any other part of the API.
(Could add `Instant.now(TimeSource)`, but it isn't entirely necessary)

Callers would pass around and use `TimeSource` directly, for example
by dependency injection.


Why add this interface?
I've seen various indications that there is a desire for an interface
representing a supplier of `Instant`. Specifically this desire is
driven by the "unnecessary" time zone that `java.time.Clock` contains.
Put simply, if the only thing you want is an `Instant`, then `Clock`
isn't the right API because it forces you to think about time zones.

A key thing that this interface allows is the separation of the OS
Clock from the time-zone (which should generally be linked to user
localization). A good architecture would pass `TimeSource` around the
system and combine it with a time-zone held in a `UserContext` to get
a `Clock`. The current design of java.time.* does not enable that
because the `TimeSource` concept does not exist. Developers either
have to write their own interface, or use `Clock` and ignore the time
zone.

A `Supplier<Instant>` obviously performs similar functionality, but it
lacks discoverability and understandability. Plus, injecting
generified interfaces tends to be painful.

Downsides?
None really, other than a new type in the JDK that probably should
have been in Java 8.


See this ThreeTen-Extra discussion
- https://github.com/ThreeTen/threeten-extra/issues/150

Joda-Time has a `MillisProvider` that is similar:
- https://www.joda.org/joda-time/apidocs/org/joda/time/DateTimeUtils.MillisProvider.html

Time4J has a `TimeSource`:
- https://github.com/MenoData/Time4J/blob/master/base/src/main/java/net/time4j/base/TimeSource.java

Spring has a `DateTimeContext` that separates the user localization as
per the `UserContext` described above:
- https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/format/datetime/standard/DateTimeContext.html

There is a similar concept `TimeSource` in `sun.net.httpserver`

There may be a case to name the interface `InstantSource`, however
`TimeSource` is a fairly widely understood name for this concept.


There is the potential to extend the interface with something similar
to Kotlin's `TimeMark` that would allow access to the monotonic clock,
suitable for measurement of durations without any leap second effects:
- https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-time-mark/

Feedback?

Stephen


More information about the core-libs-dev mailing list