DebugEN
科技森
专注于Java开发~每天都会更新文章~
  1. 首页
  2. Java
  3. 正文

在Java中生成随机的日期

2021年03月01日 1949点热度 0人点赞 0条评论 作者: kejisen

本文翻译自: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对象 ,我们可以:

  1. 在给定的时间毫秒范围内生成一个随机数
  2. 通过将该随机数传递给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.结论

在本教程中,我们将随机日期和时间的定义简化为随机数。然后,我们看到了这种减少如何帮助我们生成随机时间值的行为,例如时间戳,日期或时间。

标签: date java 日期
最后更新:2021年03月03日

kejisen

保持饥渴的专注,追求最佳的品质

点赞
< 上一篇
下一篇 >

文章评论

取消回复
最新 热点 随机
最新 热点 随机
【原创】记录一次失败的折腾——使用jkeymaster实现的按键监听 【原创】这些年我用过的IDEA插件 【原创】在windows上使用VNC远程连接linux桌面 我在RxJava使用线程池时遇到的问题 [原创文章] Swagger生成pdf格式的接口文档 [个人翻译]Java HTTP工具类的客户端证书认证 [原创] 如何从 Git 的提交历史记录中删除大文件 [翻译] 创建一个只读的Repository接口(Spring Data) [翻译] 反射的用法——用Java调用私有方法 Java 虚拟机最多可以支持多少个线程? 排查Hibernate的慢查询日志–这是查找慢查询的最简单方法 [翻译] 使用apache poi在excel文件中插入一行数据 [翻译] 在Spring 中@EntityScan与@ComponentScan注解有什么区别 [原创] 从QQ音乐网页版扒歌词的补充说明 [原创] 介绍java maven项目的多种打包方式 原创——在Java中生成随机数 将G1垃圾回收的内存使用量减少20%(翻译) [原创] java8 lambda表达式的toMap造成的空指针异常 [原创] 在Spring Boot中使用CommandLineRunner来在启动时执行代码 [转载] Kafka 节点重启失败导致数据丢失的分析排查与解决之道
Spring Boot项目修改Tomcat端口号 从QQ音乐获取并解析音乐的歌词 [个人翻译]Java HTTP工具类的客户端证书认证 [原创] java8 lambda表达式的toMap造成的空指针异常 java maven项目的几种打包方式 [翻译] 反射的用法——用Java调用私有方法 [原创] 如何使用okhttp发起application/json类型的请求 [原创] 在spring-boot中使用querydsl 【原创】记录一次失败的折腾——使用jkeymaster实现的按键监听 原创——在Java中生成随机数 Spring Boot的@RequestMapping注解中加斜杠与不加斜杠的区别 【原创】在windows上使用VNC远程连接linux桌面 [原创]javaslang(vavr.io)中Try的使用 Java 虚拟机最多可以支持多少个线程? [原创] 介绍java maven项目的多种打包方式 [原创] 在Spring Boot中使用CommandLineRunner来在启动时执行代码 使用Spring RestTemplate压缩请求 [原创] 如何使用java(javamail)发送带附件的邮件 [原创] 在ubuntu18.04上安装chromedriver 【原创】这些年我用过的IDEA插件
标签聚合
linux elasticsearch 歌词 spring springboot base64 json qq音乐 maven java

COPYRIGHT © 2020 Kejisen. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS