### Question:
RandomJodaDateTimeGenerator implements Generator<DateTime> { @Override public DateTime next() { DateTime fromTime = from.next(); long lowerBound = fromTime.getMillis(); long upperBound = to.next().getMillis(); long millis = random.nextLong(upperBound - lowerBound + 1) + lowerBound; return new DateTime(millis, timeZone == null ? fromTime.getZone() : timeZone); } RandomJodaDateTimeGenerator();  RandomJodaDateTimeGenerator(@Nonnull DateTime from, @Nonnull DateTime to);  RandomJodaDateTimeGenerator(@Nonnull Generator<DateTime> from, @Nonnull Generator<DateTime> to); private  RandomJodaDateTimeGenerator(Generator<DateTime> from, Generator<DateTime> to, DateTimeZone timeZone); static Generator<DateTime> futureDates(); static Generator<DateTime> futureDates(@Nonnull DateTime to); static Generator<DateTime> pastDates(); static Generator<DateTime> pastDates(@Nonnull DateTime from); @Override DateTime next(); Generator<DateTime> withTimeZone(DateTimeZone timeZone);  }### Answer:
@Test public void shouldGenerateRandomDateTime() { Generator<DateTime> dateTimeGenerator = new RandomJodaDateTimeGenerator(); Set<DateTime> dateTimeSet = newHashSet(); for (int i = 0; i < 100; i++) { dateTimeSet.add(dateTimeGenerator.next()); } assertThat(dateTimeSet, hasSize(100)); }
@Test public void shouldGenerateRandomDateTimeInTheSpecifiedRange() { DateTime now = now(); DateTime from = now.minusYears(100); DateTime to = now.plusYears(200); Generator<DateTime> dateTimeGenerator = new RandomJodaDateTimeGenerator(from, to); NavigableSet<DateTime> dateTimeSet = newTreeSet(); for (int i = 0; i < 1000; i++) { DateTime next = dateTimeGenerator.next(); dateTimeSet.add(next); } assertThat(dateTimeSet, hasSize(1000)); assertThat(dateTimeSet.first(), greaterThanOrEqualTo((ReadableInstant) from)); assertThat(dateTimeSet.last(), lessThanOrEqualTo((ReadableInstant) to)); }
@Test public void shouldGenerateRandomDateTimeInTheSpecifiedVerySmallRange() { DateTime from = now(); DateTime to = from.plus(1); Generator<DateTime> dateTimeGenerator = new RandomJodaDateTimeGenerator(from, to); NavigableSet<DateTime> dateTimeSet = newTreeSet(); UniqueGenerator<DateTime> dateTimeUniqueGenerator = new UniqueGenerator<>(dateTimeGenerator); dateTimeSet.add(dateTimeUniqueGenerator.next()); dateTimeSet.add(dateTimeUniqueGenerator.next()); assertThat(dateTimeSet, hasItems(from, to)); }
@Test public void shouldGenerateNowDateTime() { DateTime now = now(); Generator<DateTime> dateTimeGenerator = new RandomJodaDateTimeGenerator(now, now); assertThat(dateTimeGenerator.next(), is(now)); }
@Test public void shouldGenerateDateInTheSameTimeZoneAsFromDate() { DateTimeZone specificTimeZone = DateTimeZone.forOffsetHours(5); DateTime from = now(specificTimeZone); DateTimeZone otherTimeZone = DateTimeZone.forOffsetHours(4); DateTime to = now().plusDays(1).withZone(otherTimeZone); Generator<DateTime> randomJodaDateTimeGenerator = new RandomJodaDateTimeGenerator(from, to); DateTime generated = randomJodaDateTimeGenerator.next(); assertThat(generated.getZone(), is(specificTimeZone)); }
@Test public void shouldGenerateDateInTheSameTimeZoneAsFromDates() { Generator<DateTime> from = new Generator<DateTime>() { public int timeZoneHours = 0; @Override public DateTime next() { return now().withZone(DateTimeZone.forOffsetHours(timeZoneHours++)); } }; Generator<DateTime> to = Generators.ofInstance(now().plusDays(10)); Generator<DateTime> randomJodaDateTimeGenerator = new RandomJodaDateTimeGenerator(from, to); assertThat(randomJodaDateTimeGenerator.next().getZone(),is(DateTimeZone.forOffsetHours(0))); assertThat(randomJodaDateTimeGenerator.next().getZone(),is(DateTimeZone.forOffsetHours(1))); assertThat(randomJodaDateTimeGenerator.next().getZone(),is(DateTimeZone.forOffsetHours(2))); }