Skip to content

Commit

Permalink
Fix date/time generation when range spans midnight
Browse files Browse the repository at this point in the history
The randomizer could not generate datetime if the range span midnight, since the min/max-check failed for the LocalTimeRangeRandomizer.

Resolves #361
  • Loading branch information
johkin authored and fmbenhassine committed Oct 25, 2019
1 parent 4cea598 commit c4dbb23
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@
*/
package org.jeasy.random.randomizers.range;

import java.time.LocalDate;
import org.jeasy.random.EasyRandomParameters;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.zone.ZoneRules;

/**
* Generate a random {@link LocalDateTime} in the given range.
Expand All @@ -34,10 +39,6 @@
*/
public class LocalDateTimeRangeRandomizer extends AbstractRangeRandomizer<LocalDateTime> {

private final LocalDateRangeRandomizer localDateRangeRandomizer;

private final LocalTimeRangeRandomizer localTimeRangeRandomizer;

/**
* Create a new {@link LocalDateTimeRangeRandomizer}.
*
Expand All @@ -46,8 +47,6 @@ public class LocalDateTimeRangeRandomizer extends AbstractRangeRandomizer<LocalD
*/
public LocalDateTimeRangeRandomizer(final LocalDateTime min, final LocalDateTime max) {
super(min, max);
localDateRangeRandomizer = new LocalDateRangeRandomizer(this.min.toLocalDate(), this.max.toLocalDate());
localTimeRangeRandomizer = new LocalTimeRangeRandomizer(this.min.toLocalTime(), this.max.toLocalTime());
}

/**
Expand All @@ -59,8 +58,6 @@ public LocalDateTimeRangeRandomizer(final LocalDateTime min, final LocalDateTime
*/
public LocalDateTimeRangeRandomizer(final LocalDateTime min, final LocalDateTime max, final long seed) {
super(min, max, seed);
localDateRangeRandomizer = new LocalDateRangeRandomizer(this.min.toLocalDate(), this.max.toLocalDate(), seed);
localTimeRangeRandomizer = new LocalTimeRangeRandomizer(this.min.toLocalTime(), this.max.toLocalTime(), seed);
}

/**
Expand Down Expand Up @@ -105,9 +102,16 @@ protected LocalDateTime getDefaultMaxValue() {

@Override
public LocalDateTime getRandomValue() {
LocalDate randomLocalDate = localDateRangeRandomizer.getRandomValue();
LocalTime randomLocalTime = localTimeRangeRandomizer.getRandomValue();
return LocalDateTime.of(randomLocalDate, randomLocalTime);

long minSeconds = min.toEpochSecond(ZoneOffset.UTC);
long maxSeconds = max.toEpochSecond(ZoneOffset.UTC);
long seconds = (long) nextDouble(minSeconds, maxSeconds);
int minNanoSeconds = min.getNano();
int maxNanoSeconds = max.getNano();
long nanoSeconds = (long) nextDouble(minNanoSeconds, maxNanoSeconds);
Instant instant = Instant.ofEpochSecond(seconds, nanoSeconds);

return LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
}

}
Original file line number Diff line number Diff line change
@@ -1,38 +1,36 @@
/**
* The MIT License
*
* Copyright (c) 2019, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* <p>
* Copyright (c) 2019, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
* <p>
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* <p>
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* <p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jeasy.random.randomizers.range;

import static org.jeasy.random.randomizers.range.LocalDateTimeRangeRandomizer.aNewLocalDateTimeRangeRandomizer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.jeasy.random.randomizers.range.LocalDateTimeRangeRandomizer.aNewLocalDateTimeRangeRandomizer;

class LocalDateTimeRangeRandomizerTest extends AbstractRangeRandomizerTest<LocalDateTime> {

Expand All @@ -57,9 +55,10 @@ void generatedLocalDateTimeShouldBeWithinSpecifiedRange() {

@Test
void generatedLocalDateTimeShouldBeAlwaysTheSameForTheSameSeed() {

// Given
randomizer = aNewLocalDateTimeRangeRandomizer(minDateTime, maxDateTime, SEED);
LocalDateTime expected = LocalDateTime.of(LocalDate.ofEpochDay(163024688248L), LocalTime.ofSecondOfDay(62481));
LocalDateTime expected = LocalDateTime.parse("+446348406-04-09T16:32:16.990898895");

// When
LocalDateTime randomValue = randomizer.getRandomValue();
Expand Down Expand Up @@ -97,4 +96,19 @@ void whenSpecifiedMaxDateTimeIsNull_thenShouldUseDefaultMaxValue() {
assertThat(randomValue).isAfterOrEqualTo(minDateTime);
}

@Test
void whenMaxDateIsAfterMidnight_thenShouldNotThrowException() {
minDateTime = LocalDateTime.parse("2019-10-21T23:33:44");
maxDateTime = LocalDateTime.parse("2019-10-22T00:33:22");

// Given
randomizer = aNewLocalDateTimeRangeRandomizer(minDateTime, maxDateTime);

// when
LocalDateTime randomValue = randomizer.getRandomValue();

// Then
assertThat(randomValue).isBetween(minDateTime, maxDateTime);
}

}

0 comments on commit c4dbb23

Please sign in to comment.