如何在下午 4 点和凌晨 2 点之间的两个时间生成随机时间?

Vai*_*wal 6 java random time localtime java-time

我试过使用 -

int startSeconds = restaurant.openingTime.toSecondOfDay();
int endSeconds = restaurant.closingTime.toSecondOfDay();
LocalTime timeBetweenOpenClose = LocalTime.ofSecondOfDay(ThreadLocalRandom.current().nextInt(startSeconds, endSeconds));
Run Code Online (Sandbox Code Playgroud)

但这通常会遇到错误,如 nextInt(origin, bounds), origin 不能小于 bounds,如果 myopeningTime是 16:00:00 和closingTime02:00:00 ,则会发生这种情况。

Ekl*_*vya 5

您可以添加一天的秒数 ( 24*60*60) 当startSeconds大于时endSeconds表示第二天的秒数,并在获得随机数以一天的秒数取模后,通过有效的秒值将其转换为 LocalTime。

int secondsInDay = (int)Duration.ofDays(1).getSeconds();
if(startSeconds > endSeconds){
  endSeconds += secondsInDay;
}
LocalTime timeBetweenOpenClose = LocalTime.ofSecondOfDay(
              ThreadLocalRandom.current().nextInt(startSeconds, endSeconds) % secondsInDay);
Run Code Online (Sandbox Code Playgroud)


Arv*_*ash 5

如果不应用日期和时区,我们无法知道从下午 4 点到凌晨 2 点之间将经过多长时间。因此,我们将使用 解决它ZonedDateTime

  1. 第一步将是:ZonedDateTime通过调用获取LocalDate#atStartOfDay
ZoneId zoneId = ZoneId.systemDefault();
LocalDate.now().atStartOfDay(zoneId);
Run Code Online (Sandbox Code Playgroud)
  1. 接下来,使用ZonedDateTime#with获取ZonedDateTime具有指定时间的 a。
  2. 现在,您可以InstantZonedDateTimeusing派生ZonedDateTime#toInstant
  3. 一旦以Instant这种方式导出start 和 end s,就可以使用ThreadLocalRandom.current().nextLong生成longstart 和 end Instants范围内的值,并使用获得的值来获取所需的Instant.
  4. 最后,您可以ZonedDateTime从这个Instantusing派生 a Instant#atZone,然后使用获得所需的时间ZonedDateTime#toLocalTime

演示:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.concurrent.ThreadLocalRandom;

public class Main {
    public static void main(String[] args) {
        // Change it as per the applicable timezone e.g. ZoneId.of("Europe/London")
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate today = LocalDate.now();
        
        ZonedDateTime zdtStart = today.atStartOfDay(zoneId)
                                      .with(LocalTime.of(16, 0));
        
        ZonedDateTime zdtEnd = today.plusDays(1)
                                    .atStartOfDay(zoneId)
                                    .with(LocalTime.of(2, 0));
        
        ZonedDateTime zdtResult = 
                Instant.ofEpochMilli(
                            ThreadLocalRandom
                            .current()
                            .nextLong(
                                        zdtStart.toInstant().toEpochMilli(), 
                                        zdtEnd.toInstant().toEpochMilli()
                                    )
                        ).atZone(zoneId);
        
        LocalTime time = zdtResult.toLocalTime();
        System.out.println(time);
    }
}
Run Code Online (Sandbox Code Playgroud)

Trail: Date Time 中了解有关现代日期时间 API 的更多信息。

ONLINE DEMO 随机打印 100 次。

  • @VaibhavAgrawal A `ZonedDateTime` 是时区中的日期和时间。如果您想要特定一天的时间并且需要它在所有时区都能正常工作,那么您需要这个,因为它考虑了 DST 转换和其他时间线异常。“即时”是一个简单的时间点(顾名思义)。该代码将“LocalTime”转换为“ZonedDateTime”,再将“Instant”转换为毫秒,以便对毫秒值进行数学计算,然后转换回“Instant”、“ZonedDateTime”、“LocalTime”。 (2认同)
  • 太棒了@OleV.V。我现在明白了..谢谢!!并且_origin小于bounds_的问题得到解决,因为EpochMilli返回从_1970-01-01T00:00:00Z_纪元开始的毫秒数。尽管下午 4 点和凌晨 2 点只是示例,因此可以使用“restaurant.openingTime”而不是硬编码值“LocalTime.of(16, 0)”。并且可以使用 if 条件检查 `ZonedDateTime zdtEnd = Today.plusDays(1).atStartOfDay(zoneId).with(LocalTime.of(2, 0));` ,以便关闭时间是否在同一天内,即 `if (openingTime. isBefore(closeTime))` 那么 `plusDays(1)` 可以被删除。 (2认同)