Consider autoconfiguring a default java.time.Clock instance.

I was very surprised to see that there is currently is no autoconfigured Clock instance. I know it's only four lines of code in our application, and yet - every modern application will have them, and therefore Spring Boot can come in rescue:

@Bean
public Clock clock() {
    return Clock.systemDefaultZone();
}

I suppose this was not done because there may be people who want Clock.systemUTC() instead? Indeed, I see that, but with the exception of JEP 400 the JDK is very consistent in using the default timezone/locale etc., e.g. in ZonedDateTime.now() and all its friends.

I strongly believe the above autoconfiguration would positively please and spoil developers without taking risks. It's a small convenience, that's it.

Comment From: philwebb

Thanks for the suggestion, but I don't think we should auto-configure a Clock instance as a Spring bean. It feels too application specific and there's no obvious signal as to when it would be needed (since the class is in every JDK).

Flagging to see what other members of the team think.

Comment From: wilkinsona

I've written a few apps recently that have used the java.time APIs including the various now() methods and haven't needed a Clock for them to be sufficiently testable. As such, I don't agree that every modern application will need a Clock bean.

The one benefit that I can think of to auto-configuring a Clock is that it could be @ConditionalOnMissingBean and this would then make it easy to replace it with a FixedClock for testing.

Comment From: snicoll

I am not in favor of doing this for the reasons Phil described.

Comment From: estigma88

One of the worst problems Java had was around Date and Calendar classes: mocking them is quite hard.

Testing is important and I have seen multiple systems with requirements like: - We need to test in a specific time zone - We have a test that requires a fixed system date - We want all our systems in UTC

We have several Spring Boot apps and we create a Clock bean and injected where we need to, the Spring Boot tests override it using a fixed clock, and we also have Spring profiles that creates fixed clocks for load testing.

Those are common requirements I have seen, however, I would say: if Spring framework uses Clock heavely, it might be worth to extract it as a bean and from the client side, we will be able to override it. On the other hand, if Spring framework doesn't use Clock heavely, I am not sure it is worth to have it as a bean.

Comment From: wilkinsona

Thanks for sharing your thoughts, @estigma88.

There's no usage of java.time.Clock in Spring Boot's public API. There's a little bit of usage in Spring Framework related to task scheduling and the like. Providing a mutable clock for testing in Spring Framework was proposed and declined. In declining the issue, the Framework team suggested using profiles or a @Primary bean to override the Clock in tests. This is equivalent to the one benefit of auto-configuration that I described above.

Thanks for the suggestion, @JanecekPetr. For the reasons described above, we don't think that Spring Boot should auto-configure a Clock. If you need one in your application, a minimal amount of code is required to define one. To replace the Clock in tests, use profiles or a @Primary bean.

Comment From: JanecekPetr

Thank you for a thoughtful discussion. Indeed I wrote this in a mild shock ("How does Spring dare not do this already?!"), but after I calmed down I see your arguments. I'm happy with this resolution, thank you for considering it.

Comment From: GabrielBB

@wilkinsona Can you talk more about this:

"I've written a few apps recently that have used the java.time APIs including the various now() methods and haven't needed a Clock for them to be sufficiently testable"

How do you mock now() ?

Comment From: wilkinsona

I don't know as I didn't need to mock it.

If you have any further questions, please follow up on Stack Overflow or Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.

Comment From: birnbuazn

@GabrielBB Define a Clock bean and use the overloaded method which accepts a clock Instant.now(clock: Clock).

Then just wire up a fixed clock in your tests as suggested above. One way of doing this (in Kotlin) would be:

@Primary
@Bean
fun clock(): Clock = Clock.fixed(Instant.parse("2007-12-03T10:15:30.00Z"), ZoneId.of("UTC"))

Use @Primary to override your default Clock bean.