本文翻译自:https://www.baeldung.com/java-random-dates
1.概述
在本教程中,我们将了解如何以有界和无界的方式生成随机日期和时间。
我们将研究如何使用旧版java.util.Date API以及Java 8中新的日期时间库生成这些值。
2.随机的日期和时间
日期和时间本质上仅是一个32位整数,因此我们可以通过以下简单算法生成随机时间值:
生成一个随机的32位数字,即int类型
将生成的随机值传递给适当的日期和时间构造器或构造器
2.1 Instant-生成指定范围内的日期
java.time.Instant是Java8中新增新的日期和时间类一它们代表具体的时间点。
为了在其他两个时间范围内生成随机的Instant对象 ,我们可以:
- 在给定的时间毫秒范围内生成一个随机数
-
通过将该随机数传递给ofEpochSecond()方法来创建随机的Instant实例对象
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); }
2.2 Date-生成指定范围内的日期
java.util.Date的一个构造方法接收时间戳毫秒数。因此,我们可以使用和2.1中相同的逻辑两个Date之间生成一个随机的Date对象 :
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);
}
同样,我们应该能够验证上面代码的正确性:
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);
2.3. 没有上下界限制的Instant对象
为了生成一个完全随机的Instant,我们可以简单地生成一个随机整数并将其传递给ofEpochSecond() 方法:
public static Instant timestamp() {
return Instant.ofEpochSecond(ThreadLocalRandom.current().nextInt());
}
另外,此值应仍在Java可以处理的最小和最大Instant 值之间 :
Instant random = RandomDateTimes.timestamp();
assertThat(random).isBetween(Instant.MIN, Instant.MAX);
2.4. 没有上下界限制的Date对象
与上面相似,我们可以将一个随机值传递给Date的构造方法以生成一个随机的Date对象:
public static Date timestamp() {
return new Date(ThreadLocalRandom.current().nextInt() * 1000L);
}
由于构造方法的时间单位为毫秒,因此我们将其乘以1000,从而将32位纪元秒转换为毫秒。
当然,该值额在最小和最大日期值之间:
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);
3. 随机的日期
到目前为止,我们生成了包含日期和时间成分的随机时态。同样,我们可以使用时期的概念来生成仅包含日期成分的随机时态。
一个纪元日等于自1970年1月1日以来的天数。因此,为了生成一个随机日期,我们只需要生成一个随机数并将该数字用作纪元日即可。
3.1. 有上下界限制的日期
我们需要一个仅包含日期的对象,因此java.time.LocalDate类是一个不错的选择:
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);
}
在这里,我们使用toEpochDay() 方法将每个LocalDate 转换为其对应的int值。我们验证一下此方法是否正确:
LocalDate start = LocalDate.of(1989, Month.OCTOBER, 14);
LocalDate end = LocalDate.now();
LocalDate random = RandomDates.between(start, end);
assertThat(random).isBetween(start, end);
3.2. 没有上下界的日期
为了生成一个没有时间范围的随机日期,我们可以简单地生成一个随机的纪元日:
public static LocalDate date() {
int hundredYears = 100 * 365;
return LocalDate.ofEpochDay(ThreadLocalRandom
.current().nextInt(-hundredYears, hundredYears));
}
上面的代码从之前的100年到之后的100年中选择一个随机日期。
LocalDate randomDay = RandomDates.date();
assertThat(randomDay).isBetween(LocalDate.MIN, LocalDate.MAX);
4.随机的时间
类似于我们对日期所做的操作,我们可以生成仅包含时间的随机时态。为了做到这一点,我们认为随机时间等于表示自一天开始以来的秒数的随机数。
4.1 有范围限制的随机事件
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);
}
为了在其他两个之间生成随机时间,我们可以:
在给定时间的第二天之间生成一个随机数
使用该随机数创建一个随机时间
我们可以轻松地验证此随机时间生成算法的行为:
LocalTime morning = LocalTime.of(8, 30);
LocalTime randomTime = RandomTimes.between(LocalTime.MIDNIGHT, morning);
assertThat(randomTime)
.isBetween(LocalTime.MIDNIGHT, morning)
.isBetween(LocalTime.MIN, LocalTime.MAX);
```
### 4.2. 无界
无限制的时间值也应在00:00:00到23:59:59范围内。
```java
public static LocalTime time() {
return between(LocalTime.MIN, LocalTime.MAX);
}
5.结论
在本教程中,我们将随机日期和时间的定义简化为随机数。然后,我们看到了这种减少如何帮助我们生成随机时间值的行为,例如时间戳,日期或时间。
文章评论