如何将时间段划分为相等的间隔并找到当前时间段?

2022-09-01 16:04:28

我需要为许多用户安排定期工作。此作业将以固定的速率(即时间间隔)运行。我想在该时间间隔内为每个用户统一分配作业的执行。例如,如果间隔为4天,我会使用一致的哈希函数,每个用户的标识符来同时计划作业,例如。每4天,在第3天。

间隔相对于所有用户都相同的源即时。给定这样的原点时刻,如 Instant#EPOCH 或其他一些常量值,我如何找到当前间隔的开始日期?

我可以做

Instant now = Instant.now();
Instant origin = Instant.EPOCH;
Duration interval = Duration.ofDays(4);

Duration duration = Duration.between(origin, now);
long sinceOrigin = duration.toMillis();
long millisPerInterval = interval.toMillis();

long intervalsSince = sinceOrigin / millisPerInterval;
Instant startNext = origin.plus(interval.multipliedBy(intervalsSince));

int cursor = distributionStrategy.distribute(hashCode, millisPerInterval);

然后,我可以使用 将作业安排在相对于当前间隔开始的位置。cursorInstant

这里有很多数学,我不确定到处到处的毫秒转换是否支持实际日期。有没有一种更精确的方法来划分两个时刻之间的时间,并找到我们目前所处的一个(细分)?


答案 1

如果你只想减少这里的数学,你可以使用余数而不是除法和乘法。

long millisSinceIntervalStart = sinceOrigin % millisPerInterval;
Instant startNext = now.minusMillis(millisSinceIntervalStart);

在这里,您不必计算自原点以来经过的间隔数。只需获取自 intervalStart 以来经过的时间,然后从当前时间中减去它。

此外,您似乎指示当前间隔的开始,而不是下一个间隔。正确?startNext


答案 2

假设你真的对即时和持续时间感兴趣(即与时间段,日期,时区等无关),那么你的代码应该没问题。在这种情况下,我实际上会提前进入毫秒...这里的数学很简单。

Interval getInterval(Instant epoch, Duration duration, Instant now) {
    long epochMillis = epoch.getMillis();
    long durationMillis = duration.getMillis();

    long millisSinceEpoch = now.getMillis() - epochMillis;        
    long periodNumber = millisSinceEpoch / durationMillis;
    long start = epochMillis + periodNumber * durationMillis;
    return new Interval(start, start + durationMillis);
}

这假设你不需要担心之前 - 此时你必须做一些工作,因为你想要除法操作的底线,而不是截断到0。nowepoch

(如果您只想开始,则可以返回 。new Instant(start)


推荐