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

net.jqwik.time.internal.properties.arbitraries.DefaultLocalDateTimeArbitrary Maven / Gradle / Ivy

package net.jqwik.time.internal.properties.arbitraries;

import java.time.*;
import java.time.temporal.*;

import org.apiguardian.api.*;

import net.jqwik.api.*;
import net.jqwik.api.arbitraries.*;
import net.jqwik.time.api.*;
import net.jqwik.time.api.arbitraries.*;
import net.jqwik.time.internal.properties.arbitraries.valueRanges.*;

import static org.apiguardian.api.API.Status.*;

@API(status = INTERNAL)
public class DefaultLocalDateTimeArbitrary extends ArbitraryDecorator implements LocalDateTimeArbitrary {

	private static final LocalDateTime DEFAULT_MIN = LocalDateTime.of(DefaultLocalDateArbitrary.DEFAULT_MIN_DATE, LocalTime.MIN);
	private static final LocalDateTime DEFAULT_MAX = LocalDateTime.of(DefaultLocalDateArbitrary.DEFAULT_MAX_DATE, LocalTime.MAX);

	private final LocalDateTimeBetween dateTimeBetween = new LocalDateTimeBetween();

	private final LocalDateBetween dateBetween = new LocalDateBetween();
	private final AllowedMonths allowedMonths = new AllowedMonths();
	private final DayOfMonthBetween dayOfMonthBetween = new DayOfMonthBetween();
	private final AllowedDayOfWeeks allowedDayOfWeeks = new AllowedDayOfWeeks();

	private final LocalTimeBetween timeBetween = new LocalTimeBetween();
	private final HourBetween hourBetween = (HourBetween) new HourBetween().set(0, 23);
	private final MinuteBetween minuteBetween = (MinuteBetween) new MinuteBetween().set(0, 59);
	private final SecondBetween secondBetween = (SecondBetween) new SecondBetween().set(0, 59);
	private final OfPrecision ofPrecision = new OfPrecision();

	@Override
	protected Arbitrary arbitrary() {

		LocalDateTime effectiveMin = effectiveMin();
		LocalDateTime effectiveMax = effectiveMax(effectiveMin);

		LocalDateArbitrary dates = Dates.dates();
		TimeArbitraries times = generateTimeArbitraries(effectiveMin, effectiveMax, ofPrecision);

		dates = dates.atTheEarliest(effectiveMin.toLocalDate());
		dates = dates.atTheLatest(effectiveMax.toLocalDate());

		dates = setDateParams(dates);

		LocalDate effectiveMinDate = effectiveMin.toLocalDate();
		LocalDate effectiveMaxDate = effectiveMax.toLocalDate();

		return dates.flatMap(date -> timesByDate(times, date, effectiveMinDate, effectiveMaxDate)
										 .map(time -> LocalDateTime.of(date, time)));

	}

	private LocalDateArbitrary setDateParams(LocalDateArbitrary dates) {
		dates = dates.onlyMonths(allowedMonths.get().toArray(new Month[]{}));
		if (dayOfMonthBetween.getMin() != null && dayOfMonthBetween.getMax() != null) {
			dates = dates.dayOfMonthBetween(dayOfMonthBetween.getMin(), dayOfMonthBetween.getMax());
		}
		dates = dates.onlyDaysOfWeek(allowedDayOfWeeks.get().toArray(new DayOfWeek[]{}));
		return dates;
	}

	private LocalTimeArbitrary timesByDate(TimeArbitraries times, LocalDate date, LocalDate effectiveMin, LocalDate effectiveMax) {
		if (date.isEqual(effectiveMin)) {
			return times.firstDay;
		} else if (date.isEqual(effectiveMax)) {
			return times.lastDay;
		} else {
			return times.daysBetween;
		}
	}

	private LocalDateTime effectiveMin() {
		LocalDateTime effective = effectiveMinDate(dateTimeBetween.getMin());
		effective = effective != null ? effective : DEFAULT_MIN;
		DefaultLocalTimeArbitrary.checkTimeValueAndPrecision(effective.toLocalTime(), ofPrecision, true);
		LocalTime effectiveMinTime = DefaultLocalTimeArbitrary
										 .effectiveMin(timeBetween, hourBetween, minuteBetween, secondBetween, ofPrecision);
		LocalTime effectiveMaxTime = DefaultLocalTimeArbitrary
										 .effectiveMax(timeBetween, hourBetween, minuteBetween, secondBetween, ofPrecision);
		if (effectiveMinTime.isAfter(effectiveMaxTime)) {
			throw new IllegalArgumentException("These min/max values cannot be used with these time min/max values");
		}
		effective = effectiveMinWithMinTime(effective, effectiveMinTime, effectiveMaxTime);
		return effective;
	}

	private LocalDateTime effectiveMinDate(LocalDateTime effective) {
		if (dateBetween.getMin() == null) {
			return effective;
		} else if (effective == null || dateBetween.getMin().isAfter(effective.toLocalDate())) {
			return LocalDateTime.of(dateBetween.getMin(), LocalTime.MIN);
		} else {
			return effective;
		}
	}

	private LocalDateTime effectiveMinWithMinTime(LocalDateTime effective, LocalTime minTime, LocalTime maxTime) {
		if (effective.toLocalTime().isBefore(minTime)) {
			return LocalDateTime.of(effective.toLocalDate(), minTime);
		} else if (effective.toLocalTime().isAfter(maxTime)) {
			return LocalDateTime.of(effective.toLocalDate().plusDays(1), minTime);
		}
		return effective;
	}

	private LocalDateTime effectiveMax(LocalDateTime effectiveMin) {
		LocalDateTime effective = effectiveMaxDate(dateTimeBetween.getMax());
		effective = effective != null ? effective : LocalDateTime.of(
			DEFAULT_MAX.toLocalDate(), ofPrecision.maxPossibleLocalTime()
		);
		DefaultLocalTimeArbitrary.checkTimeValueAndPrecision(effective.toLocalTime(), ofPrecision, false);
		LocalTime effectiveMinTime = DefaultLocalTimeArbitrary
										 .effectiveMin(timeBetween, hourBetween, minuteBetween, secondBetween, ofPrecision);
		LocalTime effectiveMaxTime = DefaultLocalTimeArbitrary
										 .effectiveMax(timeBetween, hourBetween, minuteBetween, secondBetween, ofPrecision);
		effective = effectiveMaxWithMaxTime(effective, effectiveMinTime, effectiveMaxTime);
		if (effectiveMin.isAfter(effective)) {
			throw new IllegalArgumentException("These date time min/max values cannot be used with these date min/max values");
		}
		return effective;
	}

	private LocalDateTime effectiveMaxDate(LocalDateTime effective) {
		if (dateBetween.getMax() == null) {
			return effective;
		} else if (effective == null || dateBetween.getMax().isBefore(effective.toLocalDate())) {
			return LocalDateTime.of(dateBetween.getMax(), ofPrecision.maxPossibleLocalTime());
		} else {
			return effective;
		}
	}

	private LocalDateTime effectiveMaxWithMaxTime(LocalDateTime effective, LocalTime minTime, LocalTime maxTime) {
		if (effective.toLocalTime().isAfter(maxTime)) {
			return LocalDateTime.of(effective.toLocalDate(), maxTime);
		} else if (effective.toLocalTime().isBefore(minTime)) {
			return LocalDateTime.of(effective.toLocalDate().minusDays(1), minTime);
		}
		return effective;
	}

	private TimeArbitraries generateTimeArbitraries(LocalDateTime effectiveMin, LocalDateTime effectiveMax, OfPrecision ofPrecision) {
		boolean oneDay = false;
		TimeArbitraries times = new TimeArbitraries();
		if (effectiveMin.toLocalDate().isEqual(effectiveMax.toLocalDate())) {
			oneDay = true;
			times.firstDay = Times.times().between(effectiveMin.toLocalTime(), effectiveMax.toLocalTime()).ofPrecision(ofPrecision.get());
		} else {
			times.firstDay = Times.times().atTheEarliest(effectiveMin.toLocalTime()).ofPrecision(ofPrecision.get());
			times.daysBetween = Times.times().ofPrecision(ofPrecision.get());
			times.lastDay = Times.times().atTheLatest(effectiveMax.toLocalTime()).ofPrecision(ofPrecision.get());
		}
		setTimeParams(times, oneDay);
		return times;
	}

	private void setTimeParams(TimeArbitraries times, boolean oneDay) {
		if (timeBetween.getMin() != null && timeBetween.getMax() != null) {
			if (!oneDay) {
				times.firstDay = times.firstDay.atTheLatest(timeBetween.getMax());
				times.daysBetween = times.daysBetween.between(timeBetween.getMin(), timeBetween.getMax());
				times.lastDay = times.lastDay.atTheEarliest(timeBetween.getMin());
			}
		}
		times.firstDay = times.firstDay.hourBetween(hourBetween.getMin(), hourBetween.getMax())
									   .minuteBetween(minuteBetween.getMin(), minuteBetween.getMax())
									   .secondBetween(secondBetween.getMin(), secondBetween.getMax());
		if (!oneDay) {
			times.daysBetween = times.daysBetween.hourBetween(hourBetween.getMin(), hourBetween.getMax())
												 .minuteBetween(minuteBetween.getMin(), minuteBetween.getMax())
												 .secondBetween(secondBetween.getMin(), secondBetween.getMax());
			times.lastDay = times.lastDay.hourBetween(hourBetween.getMin(), hourBetween.getMax())
										 .minuteBetween(minuteBetween.getMin(), minuteBetween.getMax())
										 .secondBetween(secondBetween.getMin(), secondBetween.getMax());
		}
	}

	private void setOfPrecisionImplicitly(DefaultLocalDateTimeArbitrary clone, LocalDateTime dateTime) {
		setOfPrecisionImplicitly(clone, dateTime.toLocalTime());
	}

	private void setOfPrecisionImplicitly(DefaultLocalDateTimeArbitrary clone, LocalTime time){
		if (clone.ofPrecision.isSet()) {
			return;
		}
		ChronoUnit ofPrecision = DefaultLocalTimeArbitrary.ofPrecisionFromTime(time);
		if (clone.ofPrecision.isGreatherThan(ofPrecision)) {
			clone.ofPrecision.setProgrammatically(ofPrecision);
		}
	}

	@Override
	public LocalDateTimeArbitrary atTheEarliest(LocalDateTime min) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.dateTimeBetween.set(min, null);
		setOfPrecisionImplicitly(clone, min);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary atTheLatest(LocalDateTime max) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.dateTimeBetween.set(null, max);
		setOfPrecisionImplicitly(clone, max);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary dateBetween(LocalDate min, LocalDate max) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.dateBetween.set(min, max);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary yearBetween(Year min, Year max) {
		YearBetween yearBetween = (YearBetween) new YearBetween().set(min, max);
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.dateBetween.setYearBetween(yearBetween);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary monthBetween(Month min, Month max) {
		MonthBetween monthBetween = (MonthBetween) new MonthBetween().set(min, max);
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.allowedMonths.set(monthBetween);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary onlyMonths(Month... months) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.allowedMonths.set(months);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary dayOfMonthBetween(int min, int max) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.dayOfMonthBetween.set(min, max);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary onlyDaysOfWeek(DayOfWeek... daysOfWeek) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.allowedDayOfWeeks.set(daysOfWeek);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary timeBetween(LocalTime min, LocalTime max) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.timeBetween.set(min, max);
		clone.setOfPrecisionImplicitly(clone, min);
		clone.setOfPrecisionImplicitly(clone, max);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary hourBetween(int min, int max) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.hourBetween.set(min, max);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary minuteBetween(int min, int max) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.minuteBetween.set(min, max);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary secondBetween(int min, int max) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.secondBetween.set(min, max);
		return clone;
	}

	@Override
	public LocalDateTimeArbitrary ofPrecision(ChronoUnit ofPrecision) {
		DefaultLocalDateTimeArbitrary clone = typedClone();
		clone.ofPrecision.set(ofPrecision);
		return clone;
	}

	private static class TimeArbitraries {

		private LocalTimeArbitrary firstDay;
		private LocalTimeArbitrary daysBetween;
		private LocalTimeArbitrary lastDay;

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy