tech.sirwellington.alchemy.arguments.assertions.TimeAssertions Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of alchemy-arguments Show documentation
Show all versions of alchemy-arguments Show documentation
Part of the Alchemy Collection.
Easy, Simple, and Robust argument checking logic
for your Services, Libraries, and Scripts.
/*
* Copyright 2015 SirWellington Tech.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package tech.sirwellington.alchemy.arguments.assertions;
import java.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tech.sirwellington.alchemy.annotations.access.NonInstantiable;
import tech.sirwellington.alchemy.annotations.arguments.NonNull;
import tech.sirwellington.alchemy.arguments.AlchemyAssertion;
import tech.sirwellington.alchemy.arguments.FailedAssertionException;
import static java.lang.String.format;
import static tech.sirwellington.alchemy.arguments.Checks.Internal.checkNotNull;
import static tech.sirwellington.alchemy.arguments.Checks.Internal.checkThat;
import static tech.sirwellington.alchemy.arguments.assertions.Assertions.notNull;
import static tech.sirwellington.alchemy.arguments.assertions.NumberAssertions.greaterThan;
/**
*
* @author SirWellington
*/
@NonInstantiable
public final class TimeAssertions
{
private final static Logger LOG = LoggerFactory.getLogger(TimeAssertions.class);
TimeAssertions() throws IllegalAccessException
{
throw new IllegalAccessException("cannot instantiate");
}
/**
* Asserts that the {@link Instant} is in the past. Note that the present is constantly recalculated in order to
* stay current.
*
* @return
*/
public static AlchemyAssertion inThePast()
{
return argument ->
{
//Recalculate the present on each call to stay current
Instant present = Instant.now();
if (!argument.isBefore(present))
{
throw new FailedAssertionException(format("Expected Timestamp %s to be in the past. Now: %s", argument, present));
}
};
}
public static AlchemyAssertion before(@NonNull Instant expected)
{
checkNotNull(expected, "time cannot be null");
return argument ->
{
Assertions.notNull().check(argument);
if (!argument.isBefore(expected))
{
throw new FailedAssertionException(format("Expected Timestamp to be before %s", expected.toString()));
}
};
}
public static AlchemyAssertion inTheFuture()
{
return argument ->
{
//Recalculate the present on each call to stay current
Instant present = Instant.now();
if (!argument.isAfter(present))
{
throw new FailedAssertionException(format("Expected Timestamp %s to be in the future. Now: %s", argument, present));
}
};
}
public static AlchemyAssertion after(@NonNull Instant expected)
{
checkNotNull(expected, "time cannot be null");
return argument ->
{
Assertions.notNull().check(argument);
if (!argument.isAfter(expected))
{
throw new FailedAssertionException(format("Expected Timestamp to be after %s", expected.toString()));
}
};
}
/**
* Ensures that the {@link Instant} represents exactly Right now, at the time of checking. It does so
* within a margin-of-error of 5 milliseconds. This should be acceptable for most modern processors.
* Use {@link #nowWithinDelta(long) } for more fine-grained deltas.
*
* @return
* @see #nowWithinDelta(long)
*/
public static AlchemyAssertion rightNow()
{
return nowWithinDelta(5L);
}
/**
* Ensures that an {@link Instant} is {@link Instant#now() }, within the specified margin of error.
*
* @param marginOfErrorInMillis The Acceptable Margin-Of-Error, in Milliseconds. The instant must be within this delta.
*
* @return
* @throws IllegalArgumentException If the marginOfError is {@code < 0}.
*
* @see #rightNow()
*/
public static AlchemyAssertion nowWithinDelta(long marginOfErrorInMillis) throws IllegalArgumentException
{
checkThat(marginOfErrorInMillis >= 0, "millis must be non-negative.");
return instant ->
{
long now = Instant.now().toEpochMilli();
notNull().check(instant);
long epoch = instant.toEpochMilli();
long difference = Math.abs(epoch - now);
if (difference > marginOfErrorInMillis)
{
throw new FailedAssertionException(
"Time difference of " + difference + " exceeded margin-of-error of " + marginOfErrorInMillis + "ms");
}
};
}
/**
* Epoch version of {@link #rightNow() }.
*
* @return
*/
public static AlchemyAssertion epochRightNow()
{
return epochNowWithinDelta(5L);
}
/**
* Epoch version of {@link #nowWithinDelta(long) }.
*
* @param marginOfErrorInMillis The Acceptable Margin-Of-Error, in Milliseconds. The instant must be within this delta.
*
* @return
* @throws IllegalArgumentException If the marginOfError is {@code < 0}.
*/
public static AlchemyAssertion epochNowWithinDelta(long marginOfErrorInMillis) throws IllegalArgumentException
{
checkThat(marginOfErrorInMillis >= 0, "millis must be non-negative.");
return epoch ->
{
long now = Instant.now().toEpochMilli();
greaterThan(0L).check(epoch);
long difference = Math.abs(epoch - now);
if (difference > marginOfErrorInMillis)
{
throw new FailedAssertionException(
"Time difference of " + difference + " exceeded margin-of-error of " + marginOfErrorInMillis + "ms");
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy