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

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

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

import java.time.*;

import org.apiguardian.api.*;

import net.jqwik.api.*;
import net.jqwik.api.arbitraries.*;
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 DefaultZoneOffsetArbitrary extends ArbitraryDecorator implements ZoneOffsetArbitrary {

	public static final ZoneOffset DEFAULT_MIN = ZoneOffset.ofHoursMinutesSeconds(14, 0, 0);
	public static final ZoneOffset DEFAULT_MAX = ZoneOffset.ofHoursMinutesSeconds(-12, 0, 0);

	private final ZoneOffsetBetween zoneOffsetBetween = new ZoneOffsetBetween();

	@Override
	protected Arbitrary arbitrary() {

		ZoneOffset effectiveMin = effectiveMin();
		ZoneOffset effectiveMax = effectiveMax();

		if (effectiveMin.compareTo(effectiveMax) > 0) {
			throw new IllegalArgumentException("With this configuration is no value possible.");
		}

		int maxInt = indexOf(effectiveMin);
		int minInt = indexOf(effectiveMax);

		Arbitrary indexes = Arbitraries.integers()
												.withDistribution(RandomDistribution.uniform())
												.between(minInt, maxInt)
												.edgeCases(edgeCases -> edgeCases.includeOnly(minInt, 0, maxInt));

		return indexes.map(DefaultZoneOffsetArbitrary::offsetFromValue);

	}

	private ZoneOffset effectiveMax() {
		ZoneOffset offsetMax = zoneOffsetBetween.getMax() != null ? zoneOffsetBetween.getMax() : DEFAULT_MAX;
		boolean isNegative = offsetMax.getTotalSeconds() < 0;
		int hour = hourValue(offsetMax);
		int minute = minuteValue(offsetMax);
		int second = secondValue(offsetMax);
		if (second != 0) {
			if (!isNegative) {
				minute++;
				if (minute > 59) {
					minute -= 60;
					hour++;
				}
			}
		}
		while (minute % 15 != 0) {
			minute += isNegative ? -1 : 1;
			if (!isNegative && minute == 60) {
				minute = 0;
				hour++;
			}
		}
		if (isNegative) {
			minute = -minute;
		}
		return ZoneOffset.ofHoursMinutes(hour, minute);
	}

	private ZoneOffset effectiveMin() {
		ZoneOffset offsetMin = zoneOffsetBetween.getMin() != null ? zoneOffsetBetween.getMin() : DEFAULT_MIN;
		boolean isNegative = offsetMin.getTotalSeconds() < 0;
		int hour = hourValue(offsetMin);
		int minute = minuteValue(offsetMin);
		int second = secondValue(offsetMin);
		if (second != 0) {
			if (isNegative) {
				minute++;
				if (minute > 59) {
					minute -= 60;
					hour--;
				}
			}
		}
		while (minute % 15 != 0) {
			minute -= isNegative ? -1 : 1;
			if (isNegative && minute == 60) {
				minute = 0;
				hour--;
			}
		}
		if (isNegative) {
			minute = -minute;
		}
		return ZoneOffset.ofHoursMinutes(hour, minute);
	}

	private int indexOf(ZoneOffset effective) {
		boolean isNegative = effective.getTotalSeconds() < 0;
		int hour = hourValue(effective);
		int minuteVal = minuteValue(effective) / 15;
		if (isNegative) {
			minuteVal = -minuteVal;
		}
		return hour * 4 + minuteVal;
	}

	static private ZoneOffset offsetFromValue(int index) {
		int hour = index / 4;
		index -= hour * 4;
		int minute = index * 15;
		return ZoneOffset.ofHoursMinutes(hour, minute);
	}

	private int hourValue(ZoneOffset offset) {
		return offset.getTotalSeconds() / 3600;
	}

	private int minuteValue(ZoneOffset offset) {
		return Math.abs((offset.getTotalSeconds() % 3600) / 60);
	}

	private int secondValue(ZoneOffset offset) {
		return Math.abs(offset.getTotalSeconds() % 60);
	}

	@Override
	public ZoneOffsetArbitrary between(ZoneOffset min, ZoneOffset max) {
		if (min.compareTo(DEFAULT_MAX) > 0
				|| max.compareTo(DEFAULT_MAX) > 0
				|| min.compareTo(DEFAULT_MIN) < 0
				|| max.compareTo(DEFAULT_MIN) < 0) {
			throw new IllegalArgumentException("Offset must be between -12:00:00 and +14:00:00.");
		}

		DefaultZoneOffsetArbitrary clone = typedClone();
		clone.zoneOffsetBetween.set(min, max);
		return clone;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy