aks*_*618 3 java cron spring java-time
我在 Spring Boot 应用程序中有一个计划任务:
@Scheduled(fixedRateString = "${scheduled.task.rate}")
public void runScheduledTask() {
// ...
}
Run Code Online (Sandbox Code Playgroud)
并进行相应的测试:
@Test
public void test_scheduledTask_runs() {
await().atMost(Duration.ofMillis(scheduledTaskRate).multipliedBy(2)).untilAsserted(() -> {
Mockito.verify(scheduledTasks, Mockito.atLeastOnce()).runScheduledTask();
});
}
Run Code Online (Sandbox Code Playgroud)
现在我想使用 cron 而不是固定速率:
@Scheduled(cron = "${scheduled.task.cron}")
Run Code Online (Sandbox Code Playgroud)
现在我需要使测试适应这一点。如何获取Duration与cron表达式频率对应的对象?
Spring 提供了一个CronExpression类,可用于解析cron 表达式并获取在提供的 后触发该表达式的下一个 实例。TemporalTemporal
所以要得到一个Duration:
CronExpression cronExpression = CronExpression.parse(scheduledTaskCron);
LocalDateTime nextExecution = cronExpression.next(LocalDateTime.now());
LocalDateTime nextToNextExecution = cronExpression.next(nextExecution);
Duration durationBetweenExecutions = Duration.between(
nextExecution, nextToNextExecution
);
Run Code Online (Sandbox Code Playgroud)
请注意,Instant不能用作此处的Temporal,因为它不能表示 cron 表达式的所有组件,例如Day of Week,会出现以下异常:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfWeek
at java.base/java.time.Instant.get(Instant.java:565)
at org.springframework.scheduling.support.CronField$Type.get(CronField.java:200)
at org.springframework.scheduling.support.BitsCronField.nextOrSame(BitsCronField.java:180)
at org.springframework.scheduling.support.CronExpression.nextOrSameInternal(CronExpression.java:264)
at org.springframework.scheduling.support.CronExpression.nextOrSame(CronExpression.java:252)
at org.springframework.scheduling.support.CronExpression.next(CronExpression.java:245)
Run Code Online (Sandbox Code Playgroud)
spring 版本 < 5.3 的原始答案
Spring 提供了一个CronSequenceGenerator,可用于解析 cron 表达式并获取在提供的 后触发它的下一个 实例。DateDate
所以要得到一个Duration:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfWeek
at java.base/java.time.Instant.get(Instant.java:565)
at org.springframework.scheduling.support.CronField$Type.get(CronField.java:200)
at org.springframework.scheduling.support.BitsCronField.nextOrSame(BitsCronField.java:180)
at org.springframework.scheduling.support.CronExpression.nextOrSameInternal(CronExpression.java:264)
at org.springframework.scheduling.support.CronExpression.nextOrSame(CronExpression.java:252)
at org.springframework.scheduling.support.CronExpression.next(CronExpression.java:245)
Run Code Online (Sandbox Code Playgroud)