All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.cronn.testutils.TestClock Maven / Gradle / Ivy

The newest version!
package de.cronn.testutils;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

import org.junit.jupiter.api.Assertions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class TestClock extends Clock {

	public static final Instant DEFAULT_TEST_INSTANT = Instant.parse("2016-01-01T00:00:00.123456Z");

	private static final Logger log = LoggerFactory.getLogger(TestClock.class);

	private final AtomicReference instant;
	private final ZoneId zone;

	public TestClock() {
		this(DEFAULT_TEST_INSTANT, ZoneOffset.UTC);
	}

	public TestClock(Instant instant, ZoneId zone) {
		this.instant = new AtomicReference<>(instant);
		this.zone = zone;
	}

	public TestClock(String instant, String zone) {
		this(Instant.parse(instant), ZoneId.of(zone));
	}

	@Override
	public Instant instant() {
		return instant.get();
	}

	public ZonedDateTime now() {
		return ZonedDateTime.ofInstant(instant(), zone);
	}

	public LocalDate today() {
		return LocalDate.now(this);
	}

	public void changeInstant(Instant instant) {
		this.instant.set(instant);
		log.info("Setting test time to {}", instant);
	}

	public void reset() {
		changeInstant(DEFAULT_TEST_INSTANT);
	}

	@Override
	public ZoneId getZone() {
		return zone;
	}

	@Override
	public Clock withZone(ZoneId zone) {
		Objects.requireNonNull(zone);
		if (zone.equals(this.zone)) {
			return this;
		}
		return new TestClock(instant.get(), this.zone);
	}

	public Instant windForward(Duration duration) {
		if (duration.isNegative()) {
			throw new IllegalArgumentException(String.format("Cannot wind clock *forward* by a negative duration: %s", duration));
		}
		Instant newInstant = instant.updateAndGet(i -> i.plus(duration));
		log.info("Winding test time forward to {}", newInstant);
		return newInstant;
	}

	public void windForwardSeconds(int seconds) {
		windForward(Duration.ofSeconds(seconds));
	}

	public void windForwardHours(long hours) {
		windForward(Duration.ofHours(hours));
	}

	public void windForwardDays(long days) {
		windForward(Duration.ofDays(days));
	}

	public void windForwardToDate(LocalDate targetDate) {
		LocalDate oldDate = today();
		long daysToWindForward = ChronoUnit.DAYS.between(oldDate, targetDate);
		if (daysToWindForward < 0) {
			Instant targetInstant = instant().plus(Duration.ofDays(daysToWindForward));
			throw new IllegalArgumentException(String.format("Cannot wind clock(now=%s) *forward* to date in past(%s)", instant(), targetInstant));
		} else if (daysToWindForward > 0) {
			windForwardDays(daysToWindForward);
		} else {
			Assertions.assertEquals(targetDate, oldDate, String.format("%s must be equal to %s", targetDate, oldDate));
			log.info("Keeping test time at {}", instant());
		}
	}

	public void windBack(Duration duration) {
		if (duration.isNegative()) {
			throw new IllegalArgumentException(String.format("Cannot wind clock *backward* by a negative duration: %s", duration));
		}
		Instant newInstant = instant.updateAndGet(i -> i.minus(duration));
		log.info("Winding test time back to {}", newInstant);
	}

	public void windBackSeconds(long seconds) {
		windBack(Duration.ofSeconds(seconds));
	}

	public void windBackHours(long hours) {
		windBack(Duration.ofHours(hours));
	}

	public void windBackDays(long days) {
		windBack(Duration.ofDays(days));
	}

	public void windBackToDate(LocalDate targetDate) {
		LocalDate oldDate = today();
		long daysToWindBackward = ChronoUnit.DAYS.between(targetDate, oldDate);
		if (daysToWindBackward < 0) {
			Instant targetInstant = instant().minus(Duration.ofDays(daysToWindBackward));
			throw new IllegalArgumentException(String.format("Cannot wind clock(now=%s) *backward* to date in the future(%s)", instant(), targetInstant));
		} else if (daysToWindBackward > 0) {
			windBackDays(daysToWindBackward);
		} else {
			Assertions.assertEquals(targetDate, oldDate, String.format("%s must be equal to %s", targetDate, oldDate));
			log.info("Keeping test time at {}", instant());
		}
	}

	public static TestClock defaultBerlin() {
		return new TestClock(DEFAULT_TEST_INSTANT, ZoneId.of("Europe/Berlin"));
	}

	public static TestClock defaultUtc() {
		return new TestClock(DEFAULT_TEST_INSTANT, ZoneOffset.UTC);
	}

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy