Using the extension

Inject the clock

Inject java.time.Clock anywhere CDI is available:

import java.time.Clock;
import java.time.Instant;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

@ApplicationScoped
public class InjectClockExample {

    @Inject
    Clock clock;

    public Instant now() {
        return clock.instant();
    }
}

By default (quarkus.clock.type=system), the bean is Clock.systemUTC().

Fixed clock

Pin time to a constant instant with quarkus.clock.type=fixed and quarkus.clock.fixed-instant (ISO-8601):

quarkus.clock.type=fixed
quarkus.clock.fixed-instant=2000-01-01T00:00:00Z

quarkus.clock.fixed-instant is required when the type is fixed. The zone of the fixed clock is UTC.

Adjustable clock

Set quarkus.clock.type=adjustable to produce an AdjustableClock. The CDI bean type remains java.time.Clock; unwrap it to call mutation methods:

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

import io.quarkiverse.clock.AdjustableClock;
import io.quarkus.arc.ClientProxy;

@ApplicationScoped
public class AdjustableClockExample {

    @Inject
    Clock clock;

    public Instant forwardOneHour() {
        if (ClientProxy.unwrap(clock) instanceof AdjustableClock adjustable) {
            adjustable.forward(Duration.ofHours(1));
        }
        return clock.instant();
    }

    public Instant travelTo(Instant instant) {
        if (ClientProxy.unwrap(clock) instanceof AdjustableClock adjustable) {
            adjustable.travelTo(instant);
        }
        return clock.instant();
    }
}

AdjustableClock methods:

  • fixTo(Instant) / travelTo(Instant) — jump to an instant

  • forward(Duration) — advance by a duration

  • reset() — set the clock back to Instant.now()

Use io.quarkus.arc.ClientProxy.unwrap(clock) when the injected bean is a client proxy (typical for an @ApplicationScoped producer).