**I just announced the new *** Learn Spring * course, focused on the fundamentals of Spring 5 and Spring Boot 2:

*Learn Spring*course, focused on the fundamentals of Spring 5 and Spring Boot 2:

**>> CHECK OUT THE COURSE**

Last modified: November 7, 2019

In this tutorial, we're going to see how to generate random dates and times in bounded and unbounded fashions.

We'll be looking at how to generate these values using the legacy *java.util.Date* API and also the new date-time library from Java 8.

**Dates and times are nothing more than 32-bit integers compared to an epoch time**, so we can generate random temporal values by following this simple algorithm:

- Generate a random 32-bit number, an
*int* - Pass the generated random value to an appropriate date and time constructor or builder

** java.time.Instant is one of the new date and time additions in Java 8.** They represent instantaneous points on the time-line.

In order to generate a random *Instant *between two other ones, we can:

- Generate a random number between the epoch seconds of the given
*Instants* - Create the random
*Instant*by passing that random number to the*ofEpochSecond()*method

public static Instant between(Instant startInclusive, Instant endExclusive) { long startSeconds = startInclusive.getEpochSecond(); long endSeconds = endExclusive.getEpochSecond(); long random = ThreadLocalRandom .current() .nextLong(startSeconds, endSeconds); return Instant.ofEpochSecond(random); }

In order to achieve more throughput in multi-threaded environments, we're using the *ThreadLocalRandom* to generate our random numbers.

We can verify that the generated *Instant* is always greater than or equal to the first *Instant and *is less than the second *Instant:*

Instant hundredYearsAgo = Instant.now().minus(Duration.ofDays(100 * 365)); Instant tenDaysAgo = Instant.now().minus(Duration.ofDays(10)); Instant random = RandomDateTimes.between(hundredYearsAgo, tenDaysAgo); assertThat(random).isBetween(hundredYearsAgo, tenDaysAgo);

Remember, of course, that testing randomness is inherently non-deterministic and is generally not recommended in a real application.

Similarly, it's also possible to generate a random *Instant *after or before another one:

public static Instant after(Instant startInclusive) { return between(startInclusive, Instant.MAX); } public static Instant before(Instant upperExclusive) { return between(Instant.MIN, upperExclusive); }

**One of the java.util.Date constructors take the number of milliseconds after the epoch.** So, we can use the same algorithm to generate a random

public static Date between(Date startInclusive, Date endExclusive) { long startMillis = startInclusive.getTime(); long endMillis = endExclusive.getTime(); long randomMillisSinceEpoch = ThreadLocalRandom .current() .nextLong(startMillis, endMillis); return new Date(randomMillisSinceEpoch); }

Similarly, we should be able to verify this behavior:

long aDay = TimeUnit.DAYS.toMillis(1); long now = new Date().getTime(); Date hundredYearsAgo = new Date(now - aDay * 365 * 100); Date tenDaysAgo = new Date(now - aDay * 10); Date random = LegacyRandomDateTimes.between(hundredYearsAgo, tenDaysAgo); assertThat(random).isBetween(hundredYearsAgo, tenDaysAgo);

In order to generate a totally random *Instant*, we can simply generate a random integer and pass it to the *ofEpochSecond() *method:

public static Instant timestamp() { return Instant.ofEpochSecond(ThreadLocalRandom.current().nextInt()); }

**Using 32-bit seconds since the epoch time generates more reasonable random times, **hence we're using the *nextInt() *method here**.**

Also, this value should be still between the minimum and maximum possible *Instant *values that Java can handle:

Instant random = RandomDateTimes.timestamp(); assertThat(random).isBetween(Instant.MIN, Instant.MAX);

Similar to the bounded example, we can pass a random value to *Date's *constructor to generate a random *Date:*

public static Date timestamp() { return new Date(ThreadLocalRandom.current().nextInt() * 1000L); }

Since the* *constructor's time unit is milliseconds, we're converting the 32-bit epoch seconds to milliseconds by multiplying it by 1000.

Certainly, this value is still between the minimum and maximum possible *Date *values:

Date MIN_DATE = new Date(Long.MIN_VALUE); Date MAX_DATE = new Date(Long.MAX_VALUE); Date random = LegacyRandomDateTimes.timestamp(); assertThat(random).isBetween(MIN_DATE, MAX_DATE);

Up until now, we generated random temporals containing both date and time components. Similarly,** we can use the concept of epoch days to generate random temporals with just date components.**

An epoch day is equal to the number of days since the 1 January 1970. So in order to generate a random date, **we just have to generate a random number and use that number as the epoch day.**

We need a temporal abstraction containing only date components, so *java.time.LocalDate *seems a good candidate:

public static LocalDate between(LocalDate startInclusive, LocalDate endExclusive) { long startEpochDay = startInclusive.toEpochDay(); long endEpochDay = endExclusive.toEpochDay(); long randomDay = ThreadLocalRandom .current() .nextLong(startEpochDay, endEpochDay); return LocalDate.ofEpochDay(randomDay); }

Here we're using the *toEpochDay() *method to convert each *LocalDate *to its corresponding epoch day. Similarly, we can verify that this approach is correct:

LocalDate start = LocalDate.of(1989, Month.OCTOBER, 14); LocalDate end = LocalDate.now(); LocalDate random = RandomDates.between(start, end); assertThat(random).isBetween(start, end);

In order to generate random dates regardless of any range, we can simply generate a random epoch day:

public static LocalDate date() { int hundredYears = 100 * 365; return LocalDate.ofEpochDay(ThreadLocalRandom .current().nextInt(-hundredYears, hundredYears)); }

Our random date generator chooses a random day from 100 years before and after the epoch. Again, the rationale behind this is to generate reasonable date values:

LocalDate randomDay = RandomDates.date(); assertThat(randomDay).isBetween(LocalDate.MIN, LocalDate.MAX);

Similar to what we did with dates, we can generate random temporals with just time components. In order to do that, **we can use the second of the day concept.** That is, **a random time is equal to a random number representing the seconds since the beginning of the day.**

The *java.time.LocalTime *class is a temporal abstraction that encapsulates nothing but time components:

public static LocalTime between(LocalTime startTime, LocalTime endTime) { int startSeconds = startTime.toSecondOfDay(); int endSeconds = endTime.toSecondOfDay(); int randomTime = ThreadLocalRandom .current() .nextInt(startSeconds, endSeconds); return LocalTime.ofSecondOfDay(randomTime); }

In order to generate a random time between two others, we can:

- Generate a random number between the second of the day of the given times
- Create a random time using that random number

We can easily verify the behavior of this random time generation algorithm:

LocalTime morning = LocalTime.of(8, 30); LocalTime randomTime = RandomTimes.between(LocalTime.MIDNIGHT, morning); assertThat(randomTime) .isBetween(LocalTime.MIDNIGHT, morning) .isBetween(LocalTime.MIN, LocalTime.MAX);

Even unbounded time values should be in 00:00:00 until 23:59:59 range, so we can simply implement this logic by delegation:

public static LocalTime time() { return between(LocalTime.MIN, LocalTime.MAX); }

In this tutorial, we reduced the definition of random dates and times to random numbers. Then, we saw how this reduction helped us to generate random temporal values behaving like timestamps, dates or times.

As usual, the sample code is available over on GitHub.

## Leave a Reply