作者:YW1232602897663_231 | 来源:互联网 | 2023-07-15 18:34
我试过使用 -
int startSecOnds= restaurant.openingTime.toSecondOfDay();
int endSecOnds= restaurant.closingTime.toSecondOfDay();
LocalTime timeBetweenOpenClose = LocalTime.ofSecondOfDay(ThreadLocalRandom.current().nextInt(startSeconds, endSeconds));
但这通常会遇到错误,如 nextInt(origin, bounds), origin 不能小于 bounds,如果 myopeningTime
是 16:00:00 和closingTime
02:00:00 ,则会发生这种情况。
回答
您可以添加一天的秒数 ( 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);
回答
如果不应用日期和时区,我们无法知道从下午 4 点到凌晨 2 点之间将经过多长时间。因此,我们将使用 解决它ZonedDateTime
。
- 第一步将是:
ZonedDateTime
通过调用获取LocalDate#atStartOfDay
ZoneId zOneId= ZoneId.systemDefault();
LocalDate.now().atStartOfDay(zoneId);
- 接下来,使用
ZonedDateTime#with
获取ZonedDateTime
具有指定时间的 a。
- 现在,您可以
Instant
从ZonedDateTime
using派生ZonedDateTime#toInstant
。
- 一旦以
Instant
这种方式导出start 和 end s,就可以使用ThreadLocalRandom.current().nextLong
生成long
start 和 end Instant
s范围内的值,并使用获得的值来获取所需的Instant
.
- 最后,您可以
ZonedDateTime
从这个Instant
using派生 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);
}
}
从Trail: Date Time 中了解有关现代日期时间 API 的更多信息。
ONLINE DEMO 随机打印 100 次。
@VaibhavAgrawal A `ZonedDateTime` is a date and time in a time zone. If you want the time for a particular day and it needs to work correctly in all time zones, then you need this because it takes DST transitions and other time line anomalies into account. An `Instant` is a plain point in time (as the name says). The code converts from `LocalTime` to `ZonedDateTime` to `Instant` to milliseconds in order to do the math on the milliseconds values, then converts back to `Instant` to `ZonedDateTime` to `LocalTime`.
That's neat @OleV.V. I am getting it now..Thanks!!
And the issue of _origin less than bounds_ gets solved because EpochMilli returns the number of milliseconds from the epoch of _1970-01-01T00:00:00Z_.
Although 4 PM and 2 AM were just examples so rather than hardcoding values `LocalTime.of(16, 0)` instead `restaurant.openingTime` can be used. And `ZonedDateTime zdtEnd = today.plusDays(1).atStartOfDay(zoneId).with(LocalTime.of(2, 0));` can be checked using if condition so that if closingTime falls within same day i.e. `if (openingTime.isBefore(closingTime))` then `plusDays(1)` can be removed.