如何从cron表达式中获取Java持续时间?

yshpjwxd  于 2022-10-23  发布在  Java
关注(0)|答案(1)|浏览(575)

我在一个Spring Boot应用程序中有一个预定的任务:

@Scheduled(fixedRateString = "${scheduled.task.rate}")
public void runScheduledTask() {
    // ...
}

并进行相应的测试:

@Test
public void test_scheduledTask_runs() {
    await().atMost(Duration.ofMillis(scheduledTaskRate).multipliedBy(2)).untilAsserted(() -> {
        Mockito.verify(scheduledTasks, Mockito.atLeastOnce()).runScheduledTask();
    });
}

现在我想使用cron,而不是固定的汇率:

@Scheduled(cron = "${scheduled.task.cron}")

现在我需要调整测试以适应这一点。如何获得与cron表达式的频率相对应的Duration对象?

h43kikqp

h43kikqp1#

Spring 解决方案:

Spring提供了一个CronExpression类,可用于解析cron表达式并获得下一个Temporal示例,在该示例上,它将在所提供的Temporal之后被触发。
因此,要获得Duration

CronExpression cronExpression = CronExpression.parse(scheduledTaskCron);
LocalDateTime nextExecution = cronExpression.next(LocalDateTime.now());
LocalDateTime nextToNextExecution = cronExpression.next(nextExecution);
Duration durationBetweenExecutions = Duration.between(
        nextExecution, nextToNextExecution
);

请注意,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)

Spring版本低于5.3的原始答案
Spring提供了一个CronSequenceGenerator,可用于解析cron表达式并获得下一个Date示例,在该示例上,它将在提供的Date之后被触发。
因此,要获得Duration

CronSequenceGenerator generator = new CronSequenceGenerator(scheduledTaskCron);
Date nextExecution = generator.next(new Date());
Date nextToNextExecution = generator.next(nextExecution);
Duration durationBetweenExecutions = Duration.between(
        nextExecution.toInstant(), nextToNextExecution.toInstant()
);

相关问题