Skip to content

Commit

Permalink
Add RandomLocalTime (#59)
Browse files Browse the repository at this point in the history
Add RandomLocalTime

Resolves #57
  • Loading branch information
mkutz authored Sep 12, 2024
1 parent 9c75a16 commit 0c18aca
Show file tree
Hide file tree
Showing 9 changed files with 458 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,22 @@ include::../../../test/java/org/stubit/random/RandomDocTest.java[tag=aLocalDate]
----
include::../../../test/java/org/stubit/random/RandomDocTest.java[tag=aLocalDateInRange]
----

== Random Time

The link:{javadoc-url}/random/org/stubit/random/RandomLocalTime.html[`RandomLocalTime` class] allows to generate random LocalTimes.

[source,java,indent=0]
----
include::../../../test/java/org/stubit/random/RandomDocTest.java[tag=aLocalTimeBetween]
----

[source,java,indent=0]
----
include::../../../test/java/org/stubit/random/RandomDocTest.java[tag=aLocalTime]
----

[source,java,indent=0]
----
include::../../../test/java/org/stubit/random/RandomDocTest.java[tag=aLocalTimeInRange]
----
4 changes: 2 additions & 2 deletions manual/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ Michael Kutz <mail@michael-kutz.de>
include::chapters/00-introduction.adoc[leveloffset=1]
include::chapters/01-getting-started.adoc[leveloffset=1]
include::chapters/02-http.adoc[leveloffset=1]
include::chapters/03-random.adoc[leveloffset=1]
include::chapters/04-spring-data.adoc[leveloffset=1]
include::chapters/03-spring-data.adoc[leveloffset=1]
include::chapters/04-random.adoc[leveloffset=1]
48 changes: 48 additions & 0 deletions manual/src/test/java/org/stubit/random/RandomDocTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
import static org.stubit.random.RandomLocalDate.aLocalDate;
import static org.stubit.random.RandomLocalDate.aLocalDateBetween;
import static org.stubit.random.RandomLocalDate.aLocalDateInRange;
import static org.stubit.random.RandomLocalTime.aLocalDateBetween;
import static org.stubit.random.RandomLocalTime.aLocalTime;
import static org.stubit.random.RandomLocalTime.aLocalTimeInRange;
import static org.stubit.random.RandomNumber.aLong;
import static org.stubit.random.RandomNumber.aLongBetween;
import static org.stubit.random.RandomNumber.aNegativeInt;
Expand All @@ -28,6 +31,7 @@
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Month;
import java.time.Year;
import java.util.List;
Expand Down Expand Up @@ -307,4 +311,48 @@ void randomLocalDateBuilder_examples() {
assertThat(someTuesday1999.getYear()).isEqualTo(1999);
// end::aLocalDate[]
}

@Test
void randomLocalTime_examples() {
// tag::aLocalTimeBetween[]
LocalTime someTimeBusinessHours = aLocalDateBetween(LocalTime.of(9, 0), LocalTime.of(17, 0, 0));
assertThat(someTimeBusinessHours).isBetween(LocalTime.of(9, 0), LocalTime.of(17, 0));
// end::aLocalTimeBetween[]
}

@Test
void randomLocalTimeInRangeBuilder_examples() {
// tag::aLocalTimeInRange[]
LocalTime someLocalTime = aLocalTimeInRange().build();
assertThat(someLocalTime).isBetween(LocalTime.MIN, LocalTime.MAX);

LocalTime someFutureTime = aLocalTimeInRange().future().build();
assertThat(someFutureTime).isAfterOrEqualTo(LocalTime.now());

LocalTime somePastTime = aLocalTimeInRange().past().build();
assertThat(somePastTime).isBeforeOrEqualTo(LocalTime.now());

LocalTime someTimeAfterNoon = aLocalTimeInRange().after(LocalTime.NOON).build();
assertThat(someTimeAfterNoon).isAfterOrEqualTo(LocalTime.NOON);
// end::aLocalTimeInRange[]
}

@Test
void randomLocalTimeBuilder_examples() {
// tag::aLocalTime[]
LocalTime someLocalTime = aLocalTime().build();
assertThat(someLocalTime).isBetween(LocalTime.MIN, LocalTime.MAX);

LocalTime someTimeAt12 = aLocalTime().hour(12).build();
assertThat(someTimeAt12.getHour()).isEqualTo(12);

LocalTime someHalfTime = aLocalTime().minute(30).build();
assertThat(someHalfTime.getMinute()).isEqualTo(30);

LocalTime someTimeAlmostFull = aLocalTime().minute(59).second(59).nano(999_999_999).build();
assertThat(someTimeAlmostFull.getMinute()).isEqualTo(59);
assertThat(someTimeAlmostFull.getSecond()).isEqualTo(59);
assertThat(someTimeAlmostFull.getNano()).isEqualTo(999_999_999);
// end::aLocalTime[]
}
}
40 changes: 20 additions & 20 deletions modules/random/src/main/java/org/stubit/random/RandomLocalDate.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ public class RandomLocalDate {
private RandomLocalDate() {}

/**
* @param afterInclusive the minimum value (inclusive)
* @param beforeInclusive the maximum value (inclusive)
* @return a random {@link LocalDate} between {@code afterInclusive} and {@code beforeInclusive}
* @param after the minimum value (inclusive)
* @param before the maximum value (inclusive)
* @return a random {@link LocalDate} between {@code after} and {@code before}
*/
public static LocalDate aLocalDateBetween(LocalDate afterInclusive, LocalDate beforeInclusive) {
return aLocalDateInRange().after(afterInclusive).before(beforeInclusive).build();
public static LocalDate aLocalDateBetween(LocalDate after, LocalDate before) {
return aLocalDateInRange().after(after).before(before).build();
}

/**
Expand Down Expand Up @@ -57,9 +57,9 @@ public static class LocalDateInRangeBuilder {
private LocalDate after;
private LocalDate before;

private LocalDateInRangeBuilder(LocalDate min, LocalDate max) {
this.after = min;
this.before = max;
private LocalDateInRangeBuilder(LocalDate after, LocalDate before) {
this.after = after;
this.before = before;
}

/**
Expand All @@ -81,32 +81,32 @@ public LocalDateInRangeBuilder future() {
}

/**
* @param afterIncluding the minimum value (inclusive)
* @param after the minimum value (inclusive)
* @return this
* @throws IllegalArgumentException if {@code afterIncluding} is after {@link #before}
* @throws IllegalArgumentException if {@code after} is after {@link #before}
*/
public LocalDateInRangeBuilder after(LocalDate afterIncluding) {
if (afterIncluding.isAfter(before)) {
public LocalDateInRangeBuilder after(LocalDate after) {
if (after.isAfter(before)) {
throw new IllegalArgumentException(
"Can't set after to %s, as it must not be greater than before (%s)"
.formatted(afterIncluding, before));
.formatted(after, before));
}
this.after = afterIncluding;
this.after = after;
return this;
}

/**
* @param beforeIncluding the maximum value (inclusive)
* @param before the maximum value (inclusive)
* @return this
* @throws IllegalArgumentException if {@code beforeIncluding} is before {@link #after}
* @throws IllegalArgumentException if {@code before} is before {@link #after}
*/
public LocalDateInRangeBuilder before(LocalDate beforeIncluding) {
if (beforeIncluding.isBefore(after)) {
public LocalDateInRangeBuilder before(LocalDate before) {
if (before.isBefore(after)) {
throw new IllegalArgumentException(
"Can't set before to %s, as it must not be less than after (%s)"
.formatted(beforeIncluding, after));
.formatted(before, after));
}
this.before = beforeIncluding;
this.before = before;
return this;
}

Expand Down
168 changes: 168 additions & 0 deletions modules/random/src/main/java/org/stubit/random/RandomLocalTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package org.stubit.random;

import java.security.SecureRandom;
import java.time.LocalTime;
import org.jspecify.annotations.NullMarked;

/** Generates random {@link LocalTime}s. */
@NullMarked
public class RandomLocalTime {

private RandomLocalTime() {}

/**
* @param after the minimum value (inclusive)
* @param before the maximum value (inclusive)
* @return a random {@link LocalTime} between {@code after} and {@code before}
*/
public static LocalTime aLocalDateBetween(LocalTime after, LocalTime before) {
return aLocalTimeInRange().after(after).before(before).build();
}

/**
* @return a random {@link LocalTime} between {@link LocalTime#MIN} and now
*/
public static LocalTime aPastLocalTime() {
return aLocalTimeInRange().before(LocalTime.now()).build();
}

/**
* @return a random {@link LocalTime} between now and {@link LocalTime#MAX}
*/
public static LocalTime aFutureLocalTime() {
return aLocalTimeInRange().after(LocalTime.now()).build();
}

/**
* @return a {@link RandomLocalTime.LocalTimeInRangeBuilder} to configure the random {@link
* LocalTime}
*/
public static LocalTimeInRangeBuilder aLocalTimeInRange() {
return new LocalTimeInRangeBuilder(LocalTime.MIN, LocalTime.MAX);
}

/**
* @return a {@link LocalTimeBuilder} to configure the random {@link LocalTime}
*/
public static LocalTimeBuilder aLocalTime() {
return new LocalTimeBuilder();
}

/** Builds a random {@link LocalTime} within a specified range. */
public static class LocalTimeInRangeBuilder {

private final SecureRandom secureRandom = new SecureRandom();
private LocalTime after;
private LocalTime before;

private LocalTimeInRangeBuilder(LocalTime after, LocalTime before) {
this.after = after;
this.before = before;
}

/**
* Sets {@link #after} to {@link LocalTime#MIN} and {@link #before} to now.
*
* @return this
*/
public LocalTimeInRangeBuilder past() {
return after(LocalTime.MIN).before(LocalTime.now().minusSeconds(1));
}

/**
* Sets {@link #after} to now and {@link #before} to {@link LocalTime#MAX}.
*
* @return this
*/
public LocalTimeInRangeBuilder future() {
return after(LocalTime.now().plusSeconds(1)).before(LocalTime.MAX);
}

/**
* @param after the minimum value (inclusive).
* @return this
*/
public LocalTimeInRangeBuilder after(LocalTime after) {
if (after.isAfter(before)) {
throw new IllegalArgumentException(
"Can't set after to %s, as it must not be greater than before (%s)"
.formatted(after, before));
}
this.after = after;
return this;
}

/**
* @param before the minimum value (inclusive)
* @return this builder
*/
public LocalTimeInRangeBuilder before(LocalTime before) {
if (before.isBefore(after)) {
throw new IllegalArgumentException(
"Can't set before to %s, as it must not be less than after (%s)"
.formatted(before, after));
}
this.before = before;
return this;
}

/**
* @return a random {@link LocalTime} between {@link #after} and {@link #before}
*/
public LocalTime build() {
long minDayNano = after.toNanoOfDay();
long maxDayNano = before.toNanoOfDay() + 1;
long randomDayNano = minDayNano + secureRandom.nextLong(0, maxDayNano - minDayNano);
return LocalTime.ofNanoOfDay(randomDayNano);
}
}

/** Builds a random {@link LocalTime} with specified field values (e.g. hour, minute). */
public static class LocalTimeBuilder {

private LocalTime localTime = RandomLocalTime.aLocalTimeInRange().build();

/**
* @param hour the hour for the random {@link LocalTime}
* @return this
*/
public LocalTimeBuilder hour(int hour) {
localTime = localTime.withHour(hour);
return this;
}

/**
* @param minute the minute for the random {@link LocalTime}
* @return this
*/
public LocalTimeBuilder minute(int minute) {
localTime = localTime.withMinute(minute);
return this;
}

/**
* @param second the second for the random {@link LocalTime}
* @return this
*/
public LocalTimeBuilder second(int second) {
localTime = localTime.withSecond(second);
return this;
}

/**
* @param nano the nanosecond for the random {@link LocalTime}
* @return this
*/
public LocalTimeBuilder nano(int nano) {
localTime = localTime.withNano(nano);
return this;
}

/**
* @return the random {@link LocalTime}
*/
public LocalTime build() {
return localTime;
}
}
}
Loading

0 comments on commit 0c18aca

Please sign in to comment.