在 Spring 中,我可以使用以下方法获取下一个执行时间:
final CronSequenceGenerator generator = new CronSequenceGenerator(cronExpression);
final Date nextExecutionDate = generator.next(new Date());
但是如何从 cron 表达式中获取最后执行时间呢?
它使用二分查找来查找最后执行时间。
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import org.springframework.scheduling.support.CronExpression;
public class CronTest {
@Test
void cronTest() {
CronExpression expression = CronExpression.parse("1 0/10 * * * ?");
ZonedDateTime nextTime = expression.next(ZonedDateTime.now());
assertNotNull(nextTime);
ZonedDateTime prevTime = getPrevTime(expression, nextTime, nextTime.minusDays(1));
assertEquals(nextTime.minusMinutes(10), prevTime);
}
private ZonedDateTime getPrevTime(CronExpression expression, ZonedDateTime nextTime, ZonedDateTime mayPrevTime) {
ZonedDateTime start = mayPrevTime;
ZonedDateTime end = nextTime;
while (start.isBefore(end)) {
ZonedDateTime middle = end.minusSeconds(
TimeUnit.MILLISECONDS.toSeconds(Duration.between(start, end).toMillis() / 2));
ZonedDateTime tmpNextTime = expression.next(middle);
if (Objects.equals(tmpNextTime, nextTime)) {
end = middle.minusSeconds(1);
} else {
start = middle.plusSeconds(1);
}
}
return start;
}
}
尝试一下
import org.springframework.scheduling.support.CronSequenceGenerator;
final Date now = new Date();
// 获取上一次执行时间
CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator("0 0/5 * * * ? ");
// 获取下一次执行时间
final Date next = cronSequenceGenerator.next(now);
// 差值
final long diff = next.getTime() - now.getTime();
final Date last = new Date(now.getTime() - diff);